reshardcollection默认很慢是因为其5.0初始版本仅启用1个迁移线程,串行协调强、吞吐受限;需升级至5.0.21+/6.0.14+并满足版本、cpu、iops等硬性前提后,方可通过setparameter动态调高reshardingnummigrationthreads并发度。

reshardCollection 为什么默认很慢
MongoDB 的 reshardCollection 不是简单地复制+重路由,它要边读旧 chunk、边计算新位置、边写入新分片、边更新 config server 元数据,整个过程串行协调强,天然受限于单个迁移线程的吞吐。5.0 初始版本默认只启用 1 个迁移线程(resharding.numMigrationThreads),哪怕你磁盘 IOPS 高、网络带宽足,也跑不满——这是最常被忽略的性能瓶颈。
如何安全提高 resharing 迁移并发度
从 MongoDB 5.0.21 / 6.0.14 起,可通过 setParameter 动态调高迁移线程数,但必须满足几个硬性前提:
- 所有 mongod 实例(包括 config servers)必须运行在相同版本,且 ≥ 上述补丁版本
- CPU 负载持续低于 80%,否则线程争抢反而拖慢整体进度
- 目标分片的磁盘 IOPS 必须可支撑并发写入:例如 SSD 随机写 IOPS ≥ 3000,NVMe ≥ 10000;机械盘不建议调高
- 不能在
reshardCollection命令已启动后修改该参数,必须在执行前设置
生效命令示例(需在每个 mongos 和所有 mongod 上执行):
db.adminCommand({ setParameter: 1, reshardingNumMigrationThreads: 4 })
注意:reshardingNumMigrationThreads 是全局参数,不是 per-collection 设置项。
磁盘 IOPS 分配不当会直接卡死迁移
resharding 过程中,每个参与迁移的分片节点会同时承担三类 I/O 压力:旧 chunk 读取、新 chunk 写入、WiredTiger journal 刷盘。如果这些都挤在同一块物理盘上,IOPS 会迅速打满,表现为 reshardCollection 进度条长时间卡在某个百分比(如 37%)、currentOp 中大量 resharding 操作状态为 waitingForFlowControl 或 waitingForLock。
推荐拆分方式:
- 数据盘(
dbPath)与日志盘(journal)物理分离,避免 journal 刷盘阻塞数据写入 - config server 单独部署在低负载 SSD 上,避免元数据更新成为瓶颈
- 若使用云盘(如 AWS gp3 / Azure Premium SSD),确保预配置 IOPS ≥ 5000,且启用了突发 IOPS 能力
reshardCollection 执行期间不可控的延迟尖刺
即使调高了线程数、优化了 I/O,resharding 过程中仍会出现周期性写入阻塞:每次 chunk 迁移完成前的两秒窗口内,该 chunk 对应的所有写请求会被短暂拒绝(返回 WriteConflict 或超时),应用层感知为 P99 延迟突增。这不是 bug,是 MongoDB 为保证数据一致性强制引入的“静默期”。
应对要点:
- 不要依赖自动重试——驱动层重试可能撞上同一个静默期,建议客户端加 1–3 秒随机退避
- 监控
shardingStatistics中的resharding.migrationCount和resharding.chunkMigrationTimeMillis,若后者持续 >2000ms,说明 I/O 或 CPU 已到临界点 - 业务高峰期严禁触发 resharing;如果必须做,提前降级非核心写路径(如关闭审计日志、暂停二级索引构建)
真正难处理的不是速度,而是这个两秒静默期对强一致写场景的不可预测干扰——它不会报错,但会让部分 updateOne() 返回成功却未落盘,必须靠应用层幂等设计兜底。











