Balancer未自动启动通常因维护窗口外暂停或被手动关闭;需用sh.getBalancerState()和sh.isBalancerRunning()检查状态,再通过sh.startBalancer({maxTimeMS: 300000})安全限时限启动,并排查jumbo chunk、磁盘空间及稀疏唯一索引等隐藏问题。

Balancer为什么没自动启动?
集群扩容后数据不均衡,第一反应常是“Balancer挂了”,但更大概率是它根本没在运行——MongoDB的Balancer默认开启,但会在维护窗口外暂停,或因配置被手动关闭。检查状态最直接的方式是连接到config server执行:
sh.getBalancerState()返回
false就说明已停用;若返回true,再看sh.isBalancerRunning()是否为
true。常见误操作是运维执行过sh.stopBalancer()后忘记恢复,或在备份窗口期间触发了自动暂停且未重置。
如何安全地手动触发一次均衡?
别一上来就sh.startBalancer()让它跑一整晚。优先用sh.moveChunk()做定向迁移,验证分片间网络、权限和chunk大小是否正常。确认无误后,再用
sh.startBalancer({maxTimeMS: 300000})限制单次运行时长(单位毫秒),避免长迁移阻塞写入。注意:该命令只对当前会话生效,Balancer仍受维护窗口约束;如需绕过窗口,得配合sh.setBalancerState(true)和
sh.setMaintenanceWindow()清空维护时段。
迁移阈值调太低反而拖慢均衡速度
很多人以为把chunkSize从默认64MB降到16MB就能“更快分发”,结果发现迁移请求数暴增、config server压力飙升、甚至出现ConflictingOperationInProgress错误。根本原因是:小chunk加剧元数据锁竞争,且每个迁移都要走完整的复制、校验、清理三阶段。实际建议:
- 写入热点明确时,用
sh.splitAt()
在热点key附近预切分,比依赖自动拆分更可控 - 仅当单个chunk持续超256MB才考虑临时调小
chunkSize,操作后务必改回 - 真正影响均衡效率的是
balancer.rounds间隔(默认10分钟)和moveChunk.writeConcern设置,后者若设成{w: "majority"}在跨数据中心集群中可能卡住迁移
扩容后必须检查的三个隐藏状态
均衡卡住不一定出在Balancer本身:
- 执行
sh.status()
时关注jumbo chunks数量——这类无法拆分的chunk会被Balancer跳过,需手动sh.removeJumbo()并重建索引 - 检查各shard的
disk space剩余率,低于5%时Balancer会主动暂停迁移,日志里只报Not enough space to move chunk,不提示具体shard - 确认
_id字段是否被建了稀疏唯一索引,这会导致moveChunk失败并静默跳过,错误藏在shard server的mongod.log里,关键词是cannot move chunk with unique index


















