最直接信号是目标分片bytes_out飙升至平时3–5倍且超10分钟,源端bytes_in同步拉满而num_requests无增长;mongos日志频现Failed to receive response或Network timeout即可确认网络IO过载。

怎么判断迁移正在引发网络IO风暴
最直接的信号是:目标分片节点的 bytes_out 突然飙升至平时的 3–5 倍,且持续超过 10 分钟;同时源端 bytes_in 也同步拉满,num_requests 却没明显增长——说明不是业务请求,而是大批量数据在“硬灌”。这时候再看 mongos 日志里反复出现 Failed to receive response from shard 或 Network timeout while writing to shard,基本就能确认是网络 IO 扛不住了。
用 mongorestore 限速迁移时的关键参数组合
很多人只加 --numInsertionWorkersPerCollection,结果发现没用——因为这个参数只控制写入并发数,不控网络吞吐。真正起作用的是这组组合:
-
--numInsertionWorkersPerCollection 2:避免单集合写入锁竞争(尤其有唯一索引时) -
--writeConcern "w:1":跳过多数写确认,降低延迟压力(仅限非强一致性场景) -
--batchSize 100:减小单次网络包体积,缓解 TCP 缓冲区堆积 -
--noIndexRestore+ 后续单独建索引:索引重建本身是高IO操作,和数据导入叠加会雪上加霜
示例命令:mongorestore --host mongos_host:27017 --numInsertionWorkersPerCollection 2 --writeConcern "w:1" --batchSize 100 --noIndexRestore ./dump/
为什么 DTS 迁移也要手动限速,不能全靠“自动调节”
DTS 的“自动限速”本质是按目标库 CPU 和磁盘队列长度反向调控,但对 MongoDB 分片集群无效——它看不见 config server 路由压力、chunk 拆分触发的内部迁移、以及 mongos 的连接池耗尽。实际观测中,DTS 默认并发 8 个线程,在 3 分片集群上常导致某个 shard 的 network.bytes_out 占满千兆网卡,而其他两个 shard 几乎空转。
- 必须在 DTS 控制台手动设
最大并发数 ≤ 3(≤ 分片数) - 开启
流量控制并设置每秒最大写入量 ≤ 5MB(对应约 200–300 QPS) - 禁用
自动预热:它会在开始阶段猛刷 chunk split,极易触发 balancer 抢占带宽
监控迁移中 Balancer 是否被意外拖垮
很多人只盯着数据导入,忘了 sh.status() 里那行 balancer is currently enabled 是把双刃剑。当大量数据导入时,Balancer 会疯狂尝试迁移 chunk 来“均衡”,但它本身要走 config server 查询路由表、发 moveChunk 命令、等响应——这些全是额外网络请求。一旦网络 IO 已饱和,moveChunk 就会超时失败,失败又触发重试,形成负反馈循环。
- 迁移前务必执行
sh.stopBalancer()(注意:需等待当前迁移完成,可用sh.getBalancerState()确认) - 迁移结束后,先运行
sh.startBalancer(),再立刻执行sh.balanceOff()(临时关闭),等 10 分钟观察 chunk 分布稳定后再开 - 检查是否真停了:
sh.getBalancerState()返回true但sh.isBalancerRunning()返回false才算生效
真正麻烦的不是迁移本身,而是迁移过程中 Balancer、chunk 拆分、网络缓冲区、mongos 连接池这四层机制的隐式耦合——它们不会报错,只会让整个集群变慢、变卡、然后某天凌晨突然崩一个 shard。










