Raft 选举如何避免脑裂和 Split Vote?
简化版
Raft 允许不同任期短暂存在多个自认 Leader 的节点,但同一任期最多只有一个获得多数票的 Leader,且只有能联系多数派的 Leader 才能提交。 每个节点每个 term 只投一票,多数派相交防止同任期双主。 随机选举超时和 PreVote 降低 split vote 与无谓 term 增长,日志新旧检查防止缺少已提交日志的候选人当选。
详细版
Follower 超时后递增 term、给自己投票并发送 RequestVote。 接收者仅在候选 term 不旧、本 term 尚未投票且候选日志至少一样新时投票。 候选人获得超过半数票才成为 Leader;票平分时无人当选,等待下一轮随机超时。
旧 Leader 在分区中可能继续发送请求,但没有多数派不能提交新日志;看到更高 term 立即退位。 随机范围应大于常见尾延迟差,PreVote 让孤立节点先确认胜选可能再提升 term。 “脑裂防止”准确含义是不能有两个冲突提交历史,不是任意时刻全世界只存在一个 Leader 进程。
完整版教学
一、Raft 的 term 是逻辑时代
任期单调递增,节点看到更高 term 就更新并退为 Follower。 每次选举属于一个 term。 日志条目也记录 term,用于判断历史新旧和冲突。
Raft 不承诺旧 Leader 瞬时消失,而是保证旧 Leader 无法在没有多数派时形成冲突提交。
二、同一任期为何最多一个 Leader
节点在一个 term 最多投一票。 任意两个多数派必然相交。 若两个候选人都声称在同一 term 获多数,交集节点就必须投两票,违反规则。
5 voters -> majority = 3
candidate A voters: {1,2,3}
candidate B voters: {3,4,5}
node 3 cannot vote twice in same term
因此同 term 双多数不可能。
三、Split Vote 如何发生
Leader 故障后多个 Follower 可能同时超时并成为 Candidate。 5 节点可能出现 A 得 2 票、B 得 2 票、1 票未响应,谁都不过半。 该 term 没有 Leader,但安全性未破坏。 候选人等待新的随机选举超时,再发起更高 term 选举。
四、随机超时降低碰撞
| 场景 | 结果 | 协议如何继续 |
|---|---|---|
| 一个候选人先拿到多数票 | 当选当前 term 的 Leader | 立即发送心跳确立领导权 |
| 多个候选人平分选票 | 本 term 无人当选 | 等下一次随机超时进入更高 term |
| 候选人日志较旧 | 即使先请求也可能被拒票 | 日志新旧规则保护已提交条目 |
| 节点看到更高 term | 放弃候选人或 Leader 身份 | 更新 term 并退回 Follower |
每个节点从区间独立随机选择超时。 最先超时者通常能在其他节点成为 Candidate 前获得票。 区间过窄或小于网络/GC 尾抖动时仍会频繁冲突。 随机化降低概率,不是数学上彻底消除 split vote。
五、日志新旧检查
投票者比较候选人的 lastLogTerm,任期相同时再比较 lastLogIndex。 候选日志不够新则拒绝投票。 这确保包含已提交条目的节点不会把票给缺失这些历史的候选人。 仅比较日志长度不够,因为更长日志可能都是较旧任期的未提交条目。
六、PreVote 的作用
孤立 Follower 收不到心跳,会不断增加 term。 网络恢复后,它的高 term 会迫使健康 Leader 退位,造成无谓选举。 PreVote 先在不正式提升 term 的情况下询问能否获票,无法联系多数就不扰动集群。 PreVote 是常见扩展,仍需正确处理日志新旧和 Leader 活跃判断。
七、旧 Leader 与客户端
旧 Leader 可能接受请求并追加本地日志,但没有多数派就不能返回提交成功。 租约或 quorum 检查应让它停止线性一致读。 客户端超时请求可能已提交也可能未提交,重试必须幂等。 监控 term rate、split vote、选举耗时、Leader tenure 和拒票原因。
八、常见误区与追问
- 误区:Raft 任何时刻物理上只有一个 Leader。 分区期间可有旧 Leader,但只有多数派一侧能提交。
- 误区:Split Vote 就是脑裂数据写坏。 Split Vote 是无人获多数,主要影响活性。
- 误区:随机超时彻底消除票平分。 它只显著降低同时竞选概率。
- 误区:日志最长的候选人一定最新。 先比较 lastLogTerm,再比较 index。
- 追问:为何每 term 只能投一票? 配合多数派交集保证同 term 唯一胜者。
- 追问:PreVote 防什么? 防孤立节点恢复时用高 term 打断健康 Leader。
- 追问:少数派 Leader 能提供读吗? 只能提供明确标注的陈旧读,不能冒充线性一致读。
九、加强记忆
- term 划分领导时代。
- 每 term 一票加多数派交集保证唯一胜者。
- 日志新旧规则保护已提交历史。
- 随机超时解决活性碰撞,PreVote 减少 term 扰动。
- 安全目标是唯一提交历史,不是瞬间消灭所有旧 Leader。