一句话定义
Raft 是把共识(Consensus)拆解为「选主(Leader Election)+ 日志复制(Log Replication)+ 安全性约束」三件事的可理解算法:多数派确认日志后提交,使一组节点对外表现为一台永不丢提交数据的逻辑主机。
为什么重要
- 它是 NewSQL 与分布式 KV 的事实内核:TiKV(TiDB)、CockroachDB、etcd 全部基于 Raft——读透 Raft 等于拿到了分布式强一致数据库的钥匙。
- 它正面解决 kp-018 的 2PC 单点阻塞与 kp-023 的手动故障切换:把「谁当主、日志到哪了」变成算法自动决策。
- 理解「多数派提交」与「纪元(term)」两个概念,就能解释脑裂、数据回滚、读线性化等所有分布式诡异现象。
前置知识
kp-025(线性一致与分区权衡)、kp-023(复制与故障切换问题)。
核心概念
- 任期(Term):单调递增的逻辑时钟,每次选举加一;旧 term 的消息一律拒绝。
- 三角色:Leader(唯一处理写)、Follower(被动接收)、Candidate(竞选态)。
- 心跳与超时:Leader 周期发心跳;Follower 超时未收到即发起选举(随机化超时避免瓜分选票)。
- 日志条目:
(term, index, command);提交规则:条目被多数派持久化且 Leader 属于当前 term,才可应用到状态机。 - 安全性:选举限制(投票者只投给日志至少与自己一样新的候选者)保证已提交条目不丢。
- 线性一致读:ReadIndex(确认自己仍是 Leader 后读)或租约读,避免「旧 Leader 幽灵读」。
- 成员变更:联合共识(Joint Consensus)或单步增删,保证变更过程不出现两个多数派。
原理与机制
选举:Candidate 自增 term、给自己投票并拉票;获得多数派即当选——「多数派」保证任意两个多数派有交集,新旧 Leader 必然交接过完整日志。日志复制:Leader 接受写请求先追加本地日志,并行发送 AppendEntries 给 Followers,多数派 ack 后提交并通知应用。安全性由选举限制闭环:若某已提交条目只在一部分节点上,落选者不可能胜出,因为它比多数派「旧」。分区下的行为(与 kp-025 呼应):少数派分区中的旧 Leader 收不到多数派心跳、无法提交任何写——这正是 CAP 中选 C 的自动化实现;分区恢复后旧 Leader 看到更高 term 立即退位。对比 2PC:Raft 的「协调者」本身被多数派复制,故障切换毫秒级且不悬挂锁;对比 kp-023 的异步主从:Raft 的提交语义是多数派持久化,主库宕机零丢失。性能代价:每次写至少一次多数派 RTT + fsync,跨机房部署时延迟显著。
实例或案例
TiKV 的 Region(Range 分区,kp-024)每个是一个 Raft 组(通常 3 副本):写请求路由到 Region Leader,多数派落盘后提交;某节点宕机,剩余两节点多数派仍在,自动选出新 Leader,业务侧表现为毫秒级抖动。etcd 用单 Raft 组存储集群元数据,Kubernetes 所有资源对象经它强一致读写——「3 节点坏 1 个不影响服务」正是多数派的日常体验。读优化案例:高频配置读用 ReadIndex——Leader 先向多数派发一次心跳确认自己未被罢免,再本地读,省去日志写入,读吞吐提高一个量级且保持线性一致。
常见误区
- 认为「3 副本 Raft = 容忍 2 节点故障」:多数派要求写与选主都有 2 个存活,实际容忍 1 个故障(2N+1 容 N 故障)。
- 把 Raft 写当成比单机更快的方案:多数派 RTT + fsync 注定它慢于单机事务,买的是可用性与一致性。
- 用「读 Follower」换延迟而不做 ReadIndex:读到旧 Leader 数据,违反线性一致且难以排查。
自测题
- 为什么 Raft 要求「投票给日志至少与自己一样新的候选者」? 答:保证当选 Leader 必然持有全部已提交条目(新日志定义含更高 term 或同 term 更长索引),提交过的数据在换主后绝不回滚。
- 分区期间少数派侧的 Leader 为什么写不进去? 答:写入需要多数派持久化确认,少数派凑不齐多数派;它也无法提交选出的任何新 term,恢复后立即退位。
公式或模型
可用性:N = 2f+1 副本容忍 f 个故障;写延迟 ≈ 1 RTT(多数派) + fsync;读延迟(租约内)≈ 本地 RTT ≈ 0。选举风暴控制:随机超时区间 [T, 2T] 使瓜分选票概率趋近 0。
图示
直观类比
Raft 像三人乐队定的规矩:任何新乐谱(写)必须三人中至少两人抄到手并确认才算定稿(提交);指挥(Leader)一旦联系不上两名队友就自动降为队员,大家重新投票——票数规则保证新指挥手里的谱至少和旧指挥一样全。
与其他知识点的关系
kp-018 的 2PC 是「参与者各自单机」的跨库协议,Raft 则先让「一组节点」变成一台可靠机器再谈事务(Spanner 式路线);kp-023 的手动切换与 fencing 被 Raft 的 term 机制内建;kp-024 的每个分区可独立成一个 Raft 组。
延伸阅读
- Ongaro & Ousterhout《In Search of an Understandable Consensus Algorithm》(USENIX ATC 2014)
- Raft 官网可视化演示(raft.github.io,离线可查论文附录)