Balancer迁移打满带宽是因为默认不限速,优先保障迁移完成而非业务公平性;可通过tc限流或停Balancer+手动moveChunk控制节奏,但需注意数据倾斜、操作阻塞和config server瓶颈。

Balancer迁移为什么会打满带宽?
分片集群扩容时,Balancer 启动 chunk 迁移,会持续在 Shard 之间复制数据。默认情况下,它不设带宽限制,所有可用网络资源都可能被 mongod 进程的复制流量占用——尤其当迁移的是大集合、高写入量表,或跨可用区(如阿里云不同 VPC)部署时,iftop -i eth0 -P 很容易看到大量 27017 端口的长连接持续跑满上行/下行。
这不是“异常”,而是 Balancer 的默认行为:它优先保障迁移完成,而非业务流量公平性。
怎么限制 Balancer 的迁移带宽?
MongoDB 官方不提供直接配置“最大 Mbps”的参数,但可通过以下两个层面有效限速:
- 在
mongos或config server所在节点的系统层,用tc(traffic control)对出向流量做整形,例如限制发往目标 Shard 的27017流量不超过 20MB/s:tc qdisc add dev eth0 root tbf rate 160mbit burst 32kbit latency 400ms
- 更推荐的方式是控制迁移节奏:停掉 Balancer → 手动触发小批量迁移 → 间隔执行。用
sh.stopBalancer()停止后,再用sh.moveChunk()指定单个 chunk 迁移,并加{ waitForDelete: true }避免堆积未清理的旧数据。
注意:moveChunk 必须在 admin 数据库下执行,且目标 Shard 必须有足够空间;频繁手动调用不会自动重试失败迁移,需自己捕获 MoveChunkFailed 错误。
为什么不能只调大 net.maxIncomingConnections?
这个参数只控制单个 mongod 实例接收的客户端连接数上限,和 Balancer 内部的 shard-to-shard 复制流量无关。后者走的是内部 mongod 之间的直连,不受该配置约束。
常见误操作包括:
- 在
mongod.conf里给每个 Shard 加net.maxIncomingConnections: 5000,结果带宽照满 - 以为开启
enableSharding就自动优化了网络调度,实际 Balancer 迁移逻辑完全独立于连接管理
真正影响迁移带宽的,是 WiredTiger 缓存刷盘节奏、磁盘 I/O 能力、以及底层网络拓扑——比如同机房内网带宽充足,但跨地域专线只有 100Mbps,此时不限速就会挤占其他服务。
容易被忽略的副作用
即使成功限速,也要留意三点:
- Balancer 停止期间,新写入的数据仍会按分片键路由到原 Shard,可能导致数据倾斜加剧
-
moveChunk手动迁移时若目标 Shard 正在 compact 或备份,操作会卡住并超时,日志里出现InterruptedAtShutdown或LockTimeout - 如果 config server 使用的是低配机型(如 2C4G),限速后它反而可能因元数据更新积压成为瓶颈,
db.serverStatus().metrics.operation中write延迟会上升
实际扩容中,带宽只是表象,背后往往是分片键设计不合理或 chunk size 设置过大(默认 64MB)。建议先用 sh.status() 看 chunk 分布,再决定是调小 chunkSize,还是换分片键,而不是一上来就硬限网络。











