Raft 共识
Raft 在超时、消息延迟和领导者切换中维护复制日志的安全。本课用五服务器展示选举、当前任期提交,再把网络分成两侧:少数派可以保存新条目,但不能仅凭少数副本把它提交。
五人各持一份编号账本,领导者追加新行;当前任期的行要有三份副本证据,才越过提交边界。只写在两份上的未提交内容,可能被后来的合法领导者替换。
Raft 如何工作
画布主要状态是角色、current term、log。角色为 Follower、Candidate、Leader;term 是选举任期。日志条目由 index 与 term 共同识别,4/t5、4/t6 同位置不同条目。
Follower 接收领导者的周期 AppendEntries 心跳。选举计时到期后,增加任期、成为 Candidate、给自己投票并发送 RequestVote。每个服务器每任期最多投一票,且候选日志至少与自己的日志一样新才授票。Raft 比较最后条目的任期,再比较索引;不能只比较日志长度。五服务器须三票,超时或自投一票还不是领导者。
Leader 收到命令,先追加本地日志,再发 AppendEntries。RPC 带 prevLogIndex、prevLogTerm,接收者用它验证前缀匹配,再处理后续条目。
存储与提交分开。日志格出现条目不表示 commitIndex 已移动。对当前任期条目,Leader 知道多数派已保存后才能推进 commitIndex;Follower 稍后通过 AppendEntries 的 leaderCommit 得知边界,各自更新,没有全局同时切换的开关。
选举与复制都用三比五,但证据不同。票数条标 votes,复制条标 replicas(index n),不能把某次选举三票当成某条日志已复制三份。
逐步演示
默认 Minority partition 先健康运行,再在 2|3 分区两侧各写一条。步骤按因果边界组织,未列出全部 RPC。
- S1 是任期 5 的 Leader,五台都已提交到 index 3。
- 网络分成两侧,S1 只连得上 S2,仍自认为 Leader。
- S1 接受
set y=7,本地追加未提交4/t5。 - S2 保存并回复,两份副本,但两侧相关 commitIndex 仍为 3。
- 少数派证据停在 2/5,不能提交这条新写入。
- 比较 quorum:两个二节点集合可不相交,任意两个三节点多数集合必相交。
- 另一侧 S3 超时,进入任期 6,自投一票。
- S4、S5 授票,
{S3,S4,S5}达到 3/5,S3 当选。 - S3 接受
set z=8,也使用 index 4,但 term=6。 - S4 保存
4/t6并确认,只有两份,仍不能提交。 - S5 保存第三份并回复,使 S3 得到多数证据。
- S3 推进 commitIndex 到 4,并应用
set z=8。 - 网络恢复,S1 持有
4/t5,S3 持有已提交4/t6。 - S1 观察到任期 6,先退回 Follower。
- 前缀检查发现双方一致到
3/t5,index 4 冲突。 - S1 删除未提交
4/t5,安装4/t6,按提交边界应用命令。 - 结果显示:少数派那条写入曾占磁盘,却未进入已提交历史。
Election + commit 预设提供更短的首次流程。它故意区分第三份副本已存在、确认到达 Leader、多数证据确定、commitIndex 前进四件事。
多数派为何必须相交
固定五节点中任选两个三节点集合,至少共用一台。Raft 把这一交集与每任期一票、日志新旧检查、当前任期提交规则结合,跨任期保留已提交前缀。交集本身不能替代这些规则。
分区期间画布可同时出现 S1/t5 与 S3/t6 两个本地 Leader 视图。它们不是同任期的两个合法当选者;S1 尚未听说新任期,只有 S3 一侧能形成多数并继续提交。
恢复后 S1 先按高任期纠正角色,再用 index/term 检查前缀、替换未提交后缀。客户端若把少数派的本地追加当成功,就会把之后可被删除的值误认为已确认结果。
对服务实现的影响
本地追加或一个 Follower 回复不够确认提交,Leader 需要多数复制证据,并遵守任期规则。有的服务在提交后回复,有的还等状态机应用。超时重试仍需请求 ID 或去重;Raft 排序命令,不自动让重复客户端调用只执行一次。
三个投票服务器可容忍一个不可用,五个可容忍两个,前提是剩余多数可通信并满足协议进展条件。五节点写入需要三份而非两份证据,容错、延迟与资源开销需要权衡。这常适合控制面和元数据等需要一致决策的状态。
边界情况
- 两个 Leader 标签可以属于不同任期的本地看法。新消息到达前,旧角色认知不会自动消失。
- 同 index 不同 term 是冲突,只比较 index 会漏掉
4/t5与4/t6。 - 未提交副本可留在少数派一段时间。协议不要求立刻删除,而要求不能把不满足规则的内容当提交。
- Follower 提交滞后:S2 可存到 index 3,commitIndex 仍为 2;后续心跳传递的新边界有实际作用。
- Election + commit 聚焦运行中,S4、S5 延迟,前三台仍能选举、提交,不必等全员。
- votedFor 属于任期,新任期可重新投票,不是在旧任期重复投票。
- 旧任期条目不能只靠当前副本计数直接推进提交。Leader 提交当前任期条目时,前面的前缀才随之间接提交。
常见错误
- 超时就标 Leader,忽略候选者还需三票。
- 本地 append 就标 committed,一份只是复制计数的起点。
- 五台取两台作多数。门槛为
floor(5/2)+1=3。 - 要求所有 commitIndex 同时变化,各服务器边界知识是本地的。
- 认为网络分区让所有写入都停。此例三台侧可继续,两台侧不能提交新条目。
- 先修日志再把高任期当平局规则。高任期先改变角色,前缀规则再决定替换内容。
- 认为每条存过的日志都必须保留。保证针对已提交历史,默认
4/t5被删除正是预期行为。 - 必须五台全确认。否则两个慢节点就会阻塞整个集群,与多数派机制不同。
模型范围
固定五台、每步一个聚焦 RPC、确定的选举期限、场景内不重排消息。只画携带新提交边界的两次心跳,省略空闲心跳的周期调度、重试、批处理、持久化延迟、成员变更、pre-vote、联合共识、日志压缩与快照。分区修复直接到匹配前缀,不展示每次 nextIndex 回退;结尾 S2 的相同修复留作协议后续,不再重复画。投票与当前任期提交规则是真实规则,时间经过编排以展示证据。