讲完复制延迟,这一篇讲 failover 的核心机制——选举。当 Primary 宕机,Secondary 们怎么决定谁来当新 Primary?这个过程不是「随便选一个」,而是一套基于心跳和多数派投票的协议。理解它,才能理解 failover 的 10–30 秒写中断、为什么偶发数据回滚、以及怎么通过部署降低 failover 风险。

先把机制边界说清楚

MongoDB 的选举基于 Raft 协议的变种。核心机制是:

  • 心跳:节点之间每 2 秒互发心跳,确认彼此存活。超过 electionTimeoutMillis(默认 10 秒)收不到某节点心跳,就判定它失联。
  • 选举触发:Secondary 发现 Primary 失联,发起选举,请求其他节点投票。
  • 多数派投票:要超过半数节点同意才能当选新 Primary。
  • 降级:如果旧 Primary 恢复后发现自己已经是少数派(拿不到多数),会自动退位为 Secondary,避免脑裂(两个 Primary)。

这套机制保证了任何时刻最多只有一个 Primary,避免了脑裂导致的数据分裂。

failover 时间线

选举与 failover

一次 failover 的时间线大致是:Primary 宕机(T=0)→ 心跳超时被发现(约 10 秒)→ 发起选举并投票(几秒)→ 新 Primary 就位(总共 12–30 秒)。这期间没有 Primary,写操作全部不可用,直到新 Primary 选举完成。读操作如果配了 Secondary 读则不受影响。

选举的关键规则

心跳判定失联。节点间每 2 秒互发心跳。Secondary 连续 10 秒(electionTimeoutMillis)收不到 Primary 心跳,认为 Primary 故障,触发选举。这个超时时间是 failover 速度和误判风险的权衡——太短容易因网络抖动误触发,太长 failover 慢。

多数派投票。要超过半数节点投票同意,候选节点才能成为新 Primary。这就是为什么复制集要奇数节点——保证多数派明确,避免对称分裂。

优先级。每个节点有 priority 配置,优先级高的节点更优先当选。通常把主机房/高配节点的 priority 设高,让 Primary 优先落在它们上。priority: 0 的节点永远不会当选(适合纯备份或异地容灾节点)。

数据新旧。只有 oplog 最新(或接近最新)的节点才有资格参选。这是为了保证新 Primary 的数据不比旧 Primary 旧,避免数据倒退。如果一个 Secondary 落后太多,它不会被选为 Primary。

脑裂防护

脑裂(split-brain)是分布式系统最怕的问题:网络分区导致两个 Primary 同时存在,各自接受写入,数据分裂。MongoDB 的多数派机制从根上防止了脑裂:

  • 任何想当 Primary 的节点必须拿到多数派投票。
  • 网络分区时,只有能形成多数派的那一边能选出 Primary;少数派那边的旧 Primary 拿不到多数,会自动降级为 Secondary(停止接受写)。
  • 所以任何时刻,最多只有一个 Primary 在接受写。

这就是奇数节点的意义:3 节点分裂成 2+1,2 那边能形成多数派选主,1 那边降级;4 节点分裂成 2+2,两边都拿不到 3 票多数派,整个集群不可用。

回滚:failover 的数据代价

failover 不是完全没有代价的。如果旧 Primary 在宕机前有些写入还没复制到多数 Secondary(延迟导致的),这些写入在新 Primary 上不存在。旧 Primary 恢复重新加入时,发现这些写入不在新 Primary 的 oplog 里,会把它们回滚(rollback)——写入一个回滚文件,实质上数据丢了。

回滚是 failover 的固有风险,根源是「写入还没同步到多数节点就发生切换」。要彻底避免回滚,核心数据必须用 w: "majority" 写入——这保证写入返回成功时,多数节点已有该数据,任何 failover 都不会丢。下一篇会详细讲读写关注。

运维要点

控制 Primary 落点。通过 priority 让 Primary 优先落在主机房/高配节点,避免 failover 后 Primary 落到低配或异地节点导致性能下降。

写业务必须有重试。选举窗口(10–30 秒)写不可用是必然的,应用必须能重试写操作,否则会因短暂中断报错。

监控选举频率rs.status() 看 elections 次数。频繁选举说明节点不稳定或网络有问题,要排查根因,不能只是被动接受。

electionTimeoutMillis 调优。默认 10 秒是个平衡。网络不稳的环境可以调大(减少误判),对 failover 速度敏感的场景可以调小(更快切换),但要权衡误判风险。

判断框架

  • failover 期间写不可用(没有 Primary),写业务必须有重试。
  • 选举靠心跳 + 多数派投票,奇数节点保证多数派明确。
  • 优先级控制谁当 Primary,priority 高的优先。
  • 只有数据新的节点能参选,保证不数据倒退。
  • 多数派机制防脑裂,少数派自动降级。
  • 回滚是 failover 的数据代价,核心数据用 w: "majority" 避免回滚丢数据。

下一篇讲读写关注,把「怎么调持久性和一致性」讲透。


关于十三Tech

我是十三,All in AI Agent 方向的架构师,专注 AI 工程实践。

我相信 AI 是程序员的最佳搭档,也希望帮助每一位开发者更好地驾驭 AI。

如果你想继续跟完这套「图解 MongoDB」,欢迎关注公众号 「十三Tech」。后续会按复制集、分片集群和架构选型这条线更新。

十三Tech公众号二维码