零停机更换硬件在MongoDB分片集群中完全可行,但必须严格遵循组件级逐个替换、元数据冻结及负载均衡器控制组合策略;跳过sh.stopBalancer()或并发修改元数据将导致块迁移冲突、配置不一致甚至数据丢失。

零停机更换硬件在 MongoDB 分片集群中完全可行,但必须严格遵循组件级逐个替换 + 元数据冻结 + 负载均衡器控制的组合策略。任何跳过禁用 balancer 或并发修改元数据的操作,都会导致块迁移冲突、配置不一致甚至数据丢失。
sh.stopBalancer() 是前提,不是可选项
负载均衡器(balancer)持续调度数据块迁移,若在迁移过程中换硬件,新节点可能被分配未完成迁移的 chunk,或旧节点下线时触发异常回滚。
- 必须先连接任意
mongos执行sh.stopBalancer(),再检查确认:sh.getBalancerState()返回false - 执行后需等待当前迁移完成——用
sh.waitForBalancerOff()等待更稳妥,而非仅靠状态轮询 - MongoDB 6.0.3+ 不再自动 split,但 balancer 停止前仍会完成所有 in-progress migration,这点不能省略
配置服务器副本集(CSRS)替换顺序不能错
配置服务器是集群的“大脑”,其副本集成员替换有强顺序约束:必须先换从节点,最后换主节点,且全程不允许仲裁节点或延迟节点参与。
- 新配置服务器必须使用
--configsvr和--replSet启动,并指定相同 replica set 名称 - 每个成员的
members[n].buildIndexes必须为false,否则无法加入 CSRS - 替换主节点前,先用
rs.stepDown()主动降级,再关闭原进程;新节点加入后通过rs.reconfig()更新成员列表 - WiredTiger 存储引擎是硬性要求,
mmapv1在 MongoDB 8.0 已不支持用于配置服务器
分片节点(shard)替换要配合 removeShard 流程
直接关掉旧 shard 节点会导致 chunk 无法路由、应用报 ShardNotFound 或 NotMasterNoSlaveOk 错误。必须走标准的分片移除流程,让 balancer(虽已停)和 config server 协同清理元数据。
- 先执行
sh.removeShard("shardName"),它会触发 chunk 迁出 —— 注意:这一步依赖 balancer 已停,所以迁移不会并发发生,而是串行可控 - 等待返回显示
"msg" : "removeshard completed successfully"后,再关停旧节点 - 新 shard 节点启动后,用
sh.addShard()加入,不要手动改 config.shards 集合 - 若 shard 是副本集,确保新节点的
host:port与原成员完全一致(或更新 DNS),否则 config server 中的 host 记录不匹配会导致路由失败
容易被忽略的权限与角色陷阱
从 MongoDB 8.0 开始,部分底层操作(如直接对分片发命令)需要 directShardOperations 角色,但它极度危险——不是用来换硬件的,而是给支持团队做紧急修复的。
- 日常硬件更换全程不需要该角色;启用它反而可能绕过 balancer 控制,引发元数据写冲突
- 所有操作应以普通
clusterAdmin或root用户在mongos上执行,避免直连 shard 或 config server 修改系统集合 - 换完所有组件后,用
sh.startBalancer()恢复前,务必先运行sh.status()核查 chunk 分布是否均衡、所有 shard 状态为OK、config server 成员健康
真正卡住零停机的,从来不是磁盘拷贝速度或网络带宽,而是对 sh.stopBalancer() 的时机理解偏差、对 CSRS 成员替换顺序的轻视,以及误以为 removeShard 是“删节点”而不是“协调式疏散”。每一步背后都有 config server 的状态机在驱动,跳步=越权写元数据。


















