分片集群容灾切换需config server单中心部署、shard副本集显式控制选举与流量、应用层承担路由责任;任一层配置错误均会导致切换失败或数据错乱。

分片集群的容灾切换不能靠 mongos 自动完成,必须拆解为 config server、shard 副本集、应用路由三层分别控制——其中任何一层配置错误,都会导致切换失败或数据错乱。
config server 必须单中心部署,禁止跨机房复制
config server 是整个分片集群的“大脑”,所有路由表(chunk 分布)、分片元数据都依赖它。它用副本集形式部署,但三个节点必须全部落在同一机房(比如机房 A),否则:
- 网络抖动时
majority commit无法达成,sh.addShard()、moveChunk等操作直接卡住 -
sh.status()持续报stale config version,mongos 返回过期路由信息 - 故障后 config server 选举延迟,整个集群失去分片能力,不是高可用而是“全不可用”
正确做法:3 节点 config server 全部部署在机房 A;机房 B 只能放 mongos 实例(无状态,但需确保其连接的是机房 A 的 config server)。
每个 shard 副本集要显式控制选举与流量归属
每个 shard 本质是独立副本集,双活容灾的关键不是“能不能跨机房”,而是“故障时能否唯一降级”。默认配置下,MongoDB 不保证选举结果符合你的容灾意图。
- 给机房 A 节点设
priority: 2,机房 B 节点设priority: 1,避免平票 - 机房 B 所有节点设
votes: 0,只允许机房 A 的节点参与投票 - 用
rs.reconfig()动态加tags: { region: "A" },不能只写在rs.initiate()里 - 确认
settings.chainingAllowed: false,防止 B 机房节点从 A 机房 secondary 同步,放大延迟
漏掉任意一项,都可能在机房 A 断网后,B 机房两个节点各自发起选举,产生双主(split-brain),造成数据覆盖写入。
应用层必须承担读写路由责任,mongos 不会自动双活
mongos 本身无状态,但它强依赖 config server 的实时性。跨机房部署 mongos 不解决容灾,反而引入路由不一致风险。真正可控的切换发生在应用侧:
- 连接字符串中必须带
replicaSet参数,否则副本集感知失效 - 读流量用
readPreference=primaryPreferred&readPreferenceTags=[{region:"A"},{region:"B"}],按 tag 优先级选节点 - 写流量必须指向机房 A 的 primary(或通过 DNS 切换),不能依赖 mongos 自动发现
- 机房 A 故障时,手动触发
rs.stepDown()或调整 priority 强制机房 B 升主,再更新应用连接串或 DNS
别指望 readPreference=nearest 实现双活——它只看 ping 延迟,而跨机房延迟波动大,容易随机打到错误节点。
灾备实例只能异步同步,不能用副本集直连跨地域
阿里云等公有云上,“用私网 IP 跨地域建副本集”是常见误解。VPC 私网天然不跨地域,跨地域节点根本无法建立 TCP 连接:
-
replSetGetStatus中节点长期卡在STARTUP2或ARBITER - 日志持续报
SocketException: Host unreachable - oplog 同步完全中断,secondary 无法追平
真实跨地域容灾唯一路径是异步复制:DTS 或 MongoShake。它们拉取源集群 oplog 并重放,支持断点续传和冲突检测,但不提供强一致性保证——RPO 通常为秒级到分钟级,取决于网络与写入压力。


















