这是《MongoDB 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 MongoDB 副本集选举决定哪个成员成为 Primary。它借鉴并实现了类似 Raft 的共识思想:多数派投票、任期隔离旧主、日志进度参与选主。理解选举,才能理解故障切换时间和脑裂防护。
15.1 为什么需要选举
Primary 故障后必须满足:
- 快速选出新 Primary;
- 只有大多数成员同意;
- 拥有足够新的数据;
- 隔离旧 Primary;
- 恢复后重新加入。
多数派是防脑裂的核心:
3 members: 2 votes needed
5 members: 3 votes needed
15.2 术语
| 术语 | 说明 |
|---|---|
| term | 选举任期,任期越高优先级越高 |
| majority | 多数投票成员 |
| voting member | 有投票权的成员 |
| priority | 成为主 的优先级 |
| election timeout | 触发选举的等待时间 |
| catch-up | 新主追日志,减少回退 |
MongoDB 实现细节与 Raft 论文并不完全相同,但目标一致。
15.3 选举流程
primary heartbeat lost
-> secondary becomes candidate
-> request votes
-> majority granted
-> candidate becomes primary
-> clients update topology
节点会考虑:
- 自身健康;
- oplog 进度;
- priority;
- 其他成员状态;
- 是否能达到多数;
- 心跳连通性。
15.4 任期与旧主隔离
old primary term 10
new primary term 11
旧 Primary 恢复后:
- 发现更高任期;
- 降级为 Secondary;
- 回滚未提交到多数的写入;
- 重新同步加入。
这些未提交写入会形成回滚文件,需要人工检查和治理。
15.5 选举触发条件
常见触发:
- Primary 进程退出;
- Primary 网络隔离;
- Primary 延迟过高;
- 手动 stepDown;
- 副本集重配置;
- 维护操作。
主动切换:
rs.stepDown(120)
该命令让当前 Primary 在指定时间内不尝试重新当选。
15.6 选举时间
故障检测和选主需要时间,恢复窗口通常由以下因素决定:
- heartbeat 间隔;
- election timeout;
- 副本同步进度;
- 网络延迟;
- 节点负载;
- 多数成员健康;
- DNS 或代理层恢复。
不要假设切换毫秒级完成,应用需要处理连接错误和写超时。
15.7 投票成员设计
推荐:
| 拓扑 | 建议 |
|---|---|
| 3 节点 | 三数据节点,跨故障域 |
| 5 节点 | 可容忍两节点故障 |
| 跨机房 | 每个机房故障不破坏多数 |
| 云上 | 跨可用区,不跨账号管理复杂域 |
避免:
- 双节点副本集;
- 多数成员在同一宿主机;
- Arbiter 长期替代数据副本;
- 延迟节点参与关键读路径;
- 跨高延迟机房强求同步多数。
15.8 回滚文件
旧 Primary 上未同步到多数的写入可能回滚:
old primary write A -> not replicated
new primary commits B
old primary rejoin -> rollback A
处理:
- 查看 rollback 目录;
- 判断业务是否需要恢复;
- 通过审计或业务侧补偿;
- 不要盲目批量回灌;
- 保留复盘记录。
使用 majority 写关注可降低应用确认这类写入成功的概率。
15.9 客户端行为
切换期间可能发生:
- 连接断开;
NotPrimaryNoSecondaryOK;- 写超时;
- 重试后成功;
- 拓扑刷新延迟。
应用建议:
- 使用副本集连接串;
- 设置服务发现超时;
- 幂等重试;
- 有限退避;
- 记录请求 ID;
- 对切换窗口告警。
15.10 监控与演练
指标:
replica_set_members
member_state
elections_total
election_duration_ms
replication_lag_seconds
rollback_events_total
heartbeat_failure_total
演练:
- kill Primary;
- 断开 Primary 网络;
- 手动 stepDown;
- 恢复旧主;
- 同时关闭 Secondary;
- 跨可用区网络抖动。
验证业务恢复时间、数据一致性和客户端重试成功率。
本章小结
MongoDB 用多数派投票和任期机制选择 Primary,防止分区中出现双主。选举代价是短暂不可写,以及旧主未同步多数的写入可能回滚。生产上应合理设计投票拓扑、使用 majority 写关注并常态化演练切换。
思考题
- 为什么多数派能防止脑裂?
- term 如何隔离旧 Primary?
- 什么写入可能进入回滚文件?
- Arbiter 为什么不能替代数据副本?
- 故障切换期间应用应如何处理超时?