🔁复制状态机(Replicated State Machine)
核心思想:相同的初始状态 + 相同的操作序列 + 相同的处理规则 = 相同的最终状态。所以只要让所有节点"日志一致",它们的状态机自然就一致。
一句话:Raft 不直接复制"状态",而是复制"命令日志"。状态机只是忠实地把日志一条条执行下去。这样复制问题就被简化成"日志一致性"问题。
📜日志结构
每条日志项(Log Entry)至少包含三个字段:
| 字段 | 含义 | 作用 |
|---|---|---|
| Index | 日志槽位编号(从 1 递增) | 确定"第几条",用于匹配与对齐 |
| Term | 该条由哪个任期(Leader 任期号)写入 | 识别过期 Leader,保证单调 |
| Command | 要执行的客户端命令(如 set x=3) | 状态机真正执行的内容 |
关键约束(日志匹配原则 Log Matching):如果两个节点的日志在相同
index 处的 entry 的 term 相同,那么这两个 entry 及其之后所有 entry 都完全一致。这是 Raft 安全性的基石。🚀正常复制流程(5 步)
客户端发命令给 Leader——如
set x=5。Leader 先把命令追加到自己日志(未提交)。Leader 广播 AppendEntries——通过 RPC 把新 entry 发给所有 Follower。
Follower 追加并应答——若日志前置匹配,Follower 写入本地并返回成功。
Leader 多数派确认 → 提交——收到多数(含自己)成功后,Leader 标记该 entry 为 committed。
应用到状态机并响应——Leader 执行命令、返回客户端;后续 AppendEntries 中会带
commitIndex 通知 Follower 也提交执行。多数派(Quorum)是关键:只要
⌊N/2⌋+1 个节点写入成功即可提交,其余节点网络慢/挂掉也不阻塞。这样即使挂掉少数节点,系统仍可写。🛡️安全性规则(必考)
① Leader 完整性(Leader Completeness)
一旦某 entry 在某个任期被提交,那么后续所有任期的 Leader 的日志中都必须包含这条 entry。实现靠:选举时 Leader 必须是"日志最新最全"的节点(比较最后 entry 的 term 与 index)。
② 提交规则(只提交当前任期的 entry)
Leader 只能顺着提交自己任期内的 entry;不能仅靠"多数派有旧任期的 entry"就提交旧 entry,必须等自己任期的 entry 也提交后,旧 entry 随之提交。这是为了避免 Figure 8 经典脑裂丢数据问题。
③ 状态机安全
同 index 同 term 的 entry 命令必须相同,且一旦 apply 就不可更改——保证所有节点状态机执行同一序列。
面试高频坑:为什么不能"多数派有旧 entry 就提交"?因为旧 Leader 可能已下台,新 Leader 没这条却也凑够多数,会导致已提交数据被覆盖。Raft 用"先提交自己任期 entry 连带提交旧 entry"规避。
🔧日志冲突处理
Follower 日志可能和 Leader 不一致(网络丢包、旧 Leader 残留)。Raft 的解决方式非常"霸道但有效"。
规则:Follower 发现某 index 处 term 与 Leader 不符 → Leader 强制用自己的日志覆盖 Follower 该位置及之后的所有 entry(因为 Leader 的日志才是权威)。
Leader 如何定位冲突点
AppendEntries 带 prevLogIndex / prevLogTerm。Follower 比对:
· 不匹配 → 拒绝,并返回自己该 index 的 term;
· Leader 据此把 nextIndex 回退(一次回退一格,或跳到该 term 的起点)重试,直到匹配;
· 匹配点之后,Leader 把后续 entry 全部覆盖写入。
记忆:Follower 永远被动接受 Leader 的日志。没有"两边协商合并"——这保证了日志最终必然收敛到 Leader 的样子,简单而正确。
⚖️Raft 日志复制 vs Multi Paxos
| 维度 | Raft | Multi Paxos |
|---|---|---|
| 角色 | 强 Leader(任期制、明确) | 稳定的 Leader(隐式、易变) |
| 日志连续性 | 日志必须连续(无空洞) | 允许不连续 instance |
| 成员变更 | 内置 joint consensus | 需额外方案 |
| 理解难度 | 低(为可理解性设计) | 高(理论性强) |
| 代表 | etcd / Consul / TiKV | Spanner / 部分 ZooKeeper 早期 |
总结:Multi Paxos 是 Raft 的"前身/等价物",Raft 把 Leader 角色、日志连续性、成员变更都显式化,换来了好实现、好讲、好排错。
🎯面试要点速记
复制状态机:相同日志 → 相同状态机 → 相同结果,Raft 复制的是"命令日志"而非状态。
日志三要素:index、term、command;靠"日志匹配原则"保证一致性。
正常流程:Leader 追加 → 广播 → 多数 ACK → 提交 → apply。
多数派:只需
⌊N/2⌋+1 成功即可提交,挂少数不阻塞。安全性:Leader 完整性 + 只提交当前任期 entry(连带提交旧 entry)。
冲突:Leader 强制覆盖 Follower 不一致部分;Follower 被动接受。
必考题:"Raft 怎么保证已提交的日志不会丢?"——靠 Leader 完整性 + 选举限制(新 Leader 必须含全部已提交日志),所以新 Leader 上任后只会追加、不会覆盖已提交的 entry。