添加新分片是纯配置操作,不中断服务;需以三节点副本集形式加入,执行sh.addshard()后sh.status()显示上线但无数据,均衡器按阈值触发chunk迁移,过程影响查询延迟与io。

直接说结论:只要配置服务器和 mongos 路由层健康,新增分片节点本身不中断服务,但数据迁移过程需关注 chunk 迁移对查询延迟和磁盘 IO 的影响。
如何添加新分片节点(shard)
添加新分片是纯配置操作,不涉及停机。关键在于确保新分片以副本集形式加入,而非单节点:
- 新分片必须部署为三节点副本集(
rs.initiate()+rs.add()),否则无法通过sh.addShard()校验 - 执行
sh.addShard("rs2/10.0.1.10:27017,10.0.1.11:27017,10.0.1.12:27017"),其中rs2是副本集名称,地址列表必须包含所有成员 - 成功后,
sh.status()会显示新分片上线,但此时它还空着——chunk 迁移尚未开始 - 不要手动修改配置服务器中的
config.shards集合,所有变更必须走sh.addShard()接口
为什么 chunk 迁移会拖慢查询
迁移不是“复制完再切”,而是边读边写边校验的在线过程。每个 chunk 迁移期间:
- 源分片仍需响应该 chunk 范围内的读写请求,直到迁移确认完成
- 目标分片在接收数据时会占用大量磁盘 IO 和网络带宽,可能挤占正常查询的资源
- 如果迁移触发频繁的锁竞争(如大量更新同一分片键前缀),P95 延迟可能翻倍
- 默认迁移阈值是 64MB,但小 chunk(如 1–5MB)迁移更频繁,反而放大调度开销;大 chunk(>128MB)则单次迁移耗时长、失败重试成本高
如何控制迁移节奏避免雪崩
别依赖默认 Balance 策略。生产环境必须人工干预迁移窗口与速率:
- 用
sh.setBalancerState(false)暂停自动均衡,改用moveChunk手动调度(例如只在凌晨低峰期迁移) - 通过
sh.startBalancer({maxChunkMoveTimeMillis: 300000})限制单次迁移超时,防止卡死 - 监控
config.migrations集合,检查是否有长期 pending 的迁移任务 - 迁移中若发现某分片
db.currentOp({secs_running: {$gt: 300}})出现大量迁移相关操作,立即暂停并检查网络或磁盘瓶颈
扩容后必须验证的三件事
加完节点、迁完数据,不代表就稳了。最容易被跳过的验证点:
- 查
sh.status()中每个分片的chunks数量是否趋近均衡(允许 ±15%,超过就要查分片键设计问题) - 跑一次跨分片聚合(如
db.orders.aggregate([{$group: {_id: "$status", count: {$sum: 1}}}])),确认 mongos 能正确合并结果,且不报ExceededTimeLimit - 检查新分片上的副本集状态:
rs.status().members[n].stateStr必须是PRIMARY或SECONDARY,不能是STARTUP2或RECOVERING
真正麻烦的从来不是加机器,而是分片键选得窄、范围太集中,或者没预估好未来两年的数据倾斜趋势——这些在扩容时才会彻底暴露出来。











