Config Server 副本集扩容必须停机并重置初始化,不能用 rs.add() 或 rs.reconfig();需统一启动参数、清空新节点数据目录、全量声明成员后执行 rs.initiate(),再同步更新 mongos 的 --configdb 并重启。

Config Server 副本集不能靠 rs.add() 直接加节点
分片集群的 Config Server 必须是 3 成员(或奇数)的副本集,但它的扩容不是普通副本集那套逻辑。你执行 rs.add() 会失败,报错类似 not authorized on admin to execute command { replSetReconfig: 1 } 或直接拒绝连接——因为 mongos 不允许你动 config server 的配置,它自己管着呢。
真正能生效的方式只有一种:停掉整个 config server 副本集,逐个更新每个节点的 mongod 启动参数,再按新拓扑重启。这不是热操作,必须计划停机窗口。
- 所有 config server 节点必须使用
--configsvr启动参数(MongoDB 4.2+ 强制要求) - 新节点的
--dbpath必须为空,且目录权限正确;不能复用旧数据目录 - 必须确保所有节点的
--replSet名称完全一致(比如configRepl),大小写敏感 - 启动顺序有依赖:先起已有主节点,等它进入
PRIMARY状态,再起新节点
扩容前必须改 mongos 的 --configdb 参数
mongos 不是从副本集自动发现节点的,它只认 --configdb 启动时写的那个字符串。哪怕你把 config server 副本集扩到 5 个节点,只要 --configdb 还写着老的 3 个地址,mongos 就永远连不上新节点,也看不到新成员状态。
这个参数格式是逗号分隔的 host:port 列表,例如:configRepl/10.0.1.10:27019,10.0.1.11:27019,10.0.1.12:27019。扩容后要把它改成含 5 个地址的新字符串,然后重启 mongos 进程。
- 修改前确认所有 config server 节点已正常运行并完成初始化(
rs.status().members显示全部stateStr: "SECONDARY"或一个"PRIMARY") - mongos 重启是滚动式的,不能全停;建议逐台更新,避免路由中断
- 如果用了 DNS SRV 记录(
--configdb mongodb+srv://...),则无需改 mongos 参数,但 config server 自身仍需手动扩容
副本集初始化必须用 rs.initiate() 而非 rs.reconfig()
config server 副本集一旦初始化过,就不能用 rs.reconfig() 动态加节点——这是 MongoDB 内部限制,和普通副本集不同。你只能在所有节点都启动、但尚未初始化的状态下,用 rs.initiate() 一次性声明全部成员。
典型流程是:清空新节点数据目录 → 所有节点以 --configsvr --replSet configRepl 启动 → 连任意一个节点的 mongo --port 27019 → 执行 rs.initiate({ _id: "configRepl", configsvr: true, members: [ /* 全量 5 个成员 */ ] })。
-
members数组里每个对象必须包含_id(整数)、host(完整host:port)、priority(建议全设为 1,避免意外选举) - 不能漏掉任何一个已有节点;少一个,initiate 就失败,且无法补救,只能重来
- 执行
rs.initiate()后,副本集状态要等至少 30 秒才稳定;立刻查rs.status()可能显示STARTUP2,属正常
扩容后 config server 的读写延迟和磁盘 IO 会上升
多一个 config server 节点不等于性能变好。相反,每次元数据变更(比如 chunk 拆分、迁移)都要同步到所有成员,写入路径变长。5 节点比 3 节点平均多出 15–25% 的 config server 写延迟,尤其在频繁 balancer 活动时明显。
更关键的是,所有 config server 节点都会持续写 oplog 和 journal,磁盘 IO 压力线性增长。如果你原来用的是 NVMe SSD,问题不大;但要是混搭 SATA 盘或云盘 IOPS 有限,新增节点可能拖慢整个分片集群的元数据响应速度。
- 监控重点看
config.system.sessions和config.chunks的写入延迟(单位 ms),用db.getSiblingDB("config").getCollection("chunks").stats()查大小 - 不要为了“高可用”盲目扩到 5 或 7;3 节点已满足多数场景,5 节点只适合跨机房部署且对容灾等级要求极高的情况
- 扩容后务必跑一次
sh.startBalancer()并观察sh.getBalancerStatus(),确认 balancer 能正常读取新拓扑
最麻烦的不是操作步骤,而是 config server 副本集一旦初始化失败,没有回滚机制——删数据目录重来是唯一办法。所以每一步的参数、顺序、网络连通性,都得提前验证清楚。










