一聚教程网:一个值得你收藏的教程网站

热门教程

如何监控MongoDB分片集群的平衡器状态_使用sh.status查看Balancer活动窗口

时间:2026-07-02 11:04:52 编辑:袖梨 来源:一聚教程网

sh.status()中balancer部分仅显示是否启用、是否运行中、最近成功迁移时间;不反映待迁移chunk、队列状态、延迟或分布偏差,诊断需查config.migrationHistory、mongos日志及config.chunks聚合统计。

sh.status() 返回的 balancer 部分到底在说什么

直接看 sh.status() 输出里 balancer 段,核心就三件事:是否启用、是否正在运行、最近一次成功迁移时间。它不告诉你“接下来要搬哪块 chunk”,也不显示排队中的迁移任务——这些得查 config 数据库或日志。

常见误解是把 "enabled": true 当成“此刻正在搬数据”,其实只是开关打开;而 "currentlyRunning": true 才代表有迁移任务在执行中(哪怕只有一条)。

  • "enabled": false 表示平衡器被手动停用(sh.stopBalancer()),即使集群严重倾斜也不会自动处理
  • "currentlyRunning": true"activeWindow": null,说明没设活动窗口,平衡器全天候工作
  • "lastSeen": "..." 时间戳超过 1 小时,大概率迁移卡住了,得查 config.migrationHistorymongos 日志里的 moveChunk 错误

活动窗口(activeWindow)不是定时任务,而是白名单时间段

activeWindow 是平衡器“允许干活”的时间范围,并非 cron 式调度。它只控制迁移启动时机,不中断已在进行的迁移。一旦迁移开始,就算超出窗口也会跑完。

设置方式是调用 sh.setBalancerWindow(),传入 UTC 时间段(注意不是本地时区):

sh.setBalancerWindow( { start: "22:00", stop: "06:00" } )

这个配置写在 config.settings 集合里,所有 mongos 共享。如果多个 mongos 同时执行该命令,后写的会覆盖前写的——没有合并逻辑。

  • 时间格式必须是 "HH:MM",不支持秒、时区缩写或 AM/PM
  • 跨日区间(如 "22:00""06:00")是合法的,内部按 UTC 处理
  • 删掉窗口只需设为 nullsh.setBalancerWindow(null),别用空对象
  • 修改后不会立即生效,下一个平衡周期(默认 10 分钟检查一次)才读取新配置

为什么 sh.status() 里看不到迁移延迟或 chunk 分布偏差

sh.status()balancer 块是状态快照,不是监控仪表盘。它不包含实时负载、延迟、chunk 数量差值等指标——那些得自己算。

比如判断是否失衡,不能只看 "currentlyRunning": false,还要查各 shard 的 chunk 总数:

db.getSiblingDB("config").chunks.aggregate([   { $group: { _id: "$shard", count: { $sum: 1 } } } ])

再结合 db.getSiblingDB("config").tags.find() 看分片标签规则,才能确认是不是策略导致的“假失衡”。

  • 平衡器默认每 10 分钟触发一次检查,但实际迁移频率受 chunkSize、网络延迟、目标 shard 磁盘压力影响,sh.status() 不反映这些
  • 如果某次 moveChunk 失败(如目标 shard 写满),错误只记在 mongos 日志和 config.migrationHistorysh.status() 里只会显示 "lastSeen" 停滞
  • sh.status() 输出的 "migrationCount" 是历史累计值,不是当前队列长度,无法用于判断积压

停用平衡器时,sh.stopBalancer() 和直接改 config.settings 效果不同

sh.stopBalancer() 是安全停用:它先等待当前迁移完成,再更新 config.settings 并广播给所有 mongos。而手动 update config.settings 里的 balancer 文档,会立刻生效但可能中断迁移,导致数据不一致或锁残留。

恢复时也一样:sh.startBalancer() 会校验集群健康状态(如所有 shard 可达),而直接改回 "enabled": true 不做任何检查。

  • 生产环境停平衡器务必用 sh.stopBalancer(),别绕过 shell 封装
  • 停用期间新增的 chunk(如 bulk insert)不会被自动切分,等重启后才会参与平衡——这点常被忽略
  • 如果 sh.stopBalancer() 卡住超过 30 秒,大概率有迁移阻塞,需查 config.locks"_id": "balancer"state 字段是否为 2(表示被其他操作锁住)
平衡器的状态表面简单,但 sh.status() 隐藏了太多上下文依赖:时间窗口的 UTC 语义、迁移中断的边界条件、停用操作的原子性保障。真要靠它诊断问题,得随时准备好翻 config.migrationHistory 和 mongos 日志。

热门栏目