Raft 为什么取代了 Paxos?从 DLedger 和 KRaft 的技术选型聊起

上篇留下的问题

上篇拆了 DLedger 的选主流程和日志复制机制,也对比了它和 Kafka KRaft 的差异。但有一件事我一直没有深入讲------为什么 DLedger 和 KRaft 都选择了 Raft,而不是 Paxos?

Paxos 比 Raft 早了十几年,Lamport 的论文是分布式共识领域的奠基之作。但工业界的主流系统------etcd、Consul、TiKV、RocketMQ 的 DLedger、Kafka 的 KRaft------几乎全部选择了 Raft。这不是偶然。

这篇就来回答这个问题:Paxos 做对了什么、留下了什么坑,Raft 做了什么简化,以及为什么"可理解性"在工程选型中比理论优雅更重要。

Paxos 做对了什么

Paxos 的核心贡献是在理论上证明了分布式共识是可以达成的。在 Paxos 之前,分布式共识被普遍认为是不可能的------FLP 不可能性定理证明了在异步网络中,只要有一个节点可能故障,就不存在一个既能保证安全性又能保证活性的确定性共识算法。

Paxos 绕开了这个问题:它不追求活性,只保证安全性。在多数派节点正常工作时,系统能够推进;在极端情况下(比如网络持续分区),系统可能无法达成共识,但绝不会产生不一致的结果。

这个安全性保证来自 Paxos 的核心设计:多数派承诺。一个提案要被接受,必须获得超过半数的 Acceptor 的批准。任意两个多数派必然有交集,这个交集保证了已经被接受的提案不会被后续提案覆盖。

从理论上讲,Paxos 的优雅性无可挑剔。但它的问题是:理论上的优雅不等于工程上的可实现。

Paxos 留下了什么坑

第一个坑:Basic Paxos 的活锁问题。

Basic Paxos 中不存在 Leader 角色,任何 Proposer 都可以随时提出提案。如果两个 Proposer 同时提出提案,并且提案编号不断递增,它们可能会永远互相否决,导致系统在持续性的"反复横跳"中无法推进。虽然 Lamport 给出的解决办法是"随机睡眠-重试"或"选举一个 Leader",但这些解决方式本身需要额外的机制来保证。

第二个坑:Multi-Paxos 的"没写完"。

Basic Paxos 只能就单个值达成共识。实际系统需要的是就一系列值 (日志条目)达成共识,这就是 Multi-Paxos 要解决的问题。但 Multi-Paxos 面临一个尴尬的处境:论文没有完整地描述它。

Google 工程师在《Paxos Made Live》中记录了将 Multi-Paxos 落地到 Chubby 时踩过的坑。Multi-Paxos 的工程部分------比如 Leader 选举的具体实现、日志空洞的填充、快照和日志压缩------论文里根本没有写。这意味着每个实现者都在重新发明轮子,而且很容易犯错。

第三个坑:Leader 切换时的额外开销。

在 Multi-Paxos 中,新 Leader 当选后,需要重新执行 Phase 1(Prepare 阶段)来处理那些尚未决议的日志槽位。这个过程需要额外的消息和等待,导致 Leader 频繁切换时 Multi-Paxos 的性能会明显下降。

第四个坑:状态空间太大。

Paxos 允许任何节点在任何时候提出提案,这赋予了系统极大的灵活性,但也导致状态空间爆炸。实现者需要考虑大量边界情况:提案编号冲突、网络分区恢复后的状态合并、多个 Proposer 同时活跃时的行为......每个场景都需要仔细推理,而分布式系统的状态组合是指数级的。

Raft 做了什么简化

Raft 的设计目标很明确:可理解性。论文标题就叫《In Search of an Understandable Consensus Algorithm》。

这个目标不是口号,它直接影响了 Raft 的每一个设计决策。

简化一:强 Leader 模型。

Raft 引入了强 Leader:所有写操作必须经过 Leader,日志只从 Leader 单向流向 Follower。这直接规避了 Basic Paxos 的活锁问题------只有一个节点能提出提案,不存在互相竞争的情况。

同时,随机选举超时机制进一步降低了多个 Candidate 同时发起选举的概率。

简化二:问题分解。

Raft 把共识问题拆解为三个完全正交 的子问题:领导者选举、日志复制、安全性。每个子问题都有独立的处理逻辑,实现者可以逐个理解和验证。

相比之下,Paxos 的组件是"hard to separate"的------准备、批准、学习三个阶段紧密耦合,难以独立推理。

简化三:选举安全性的显式约束。

这是 Raft 和 Paxos 最核心的算法差异:Raft 只允许拥有最新日志的节点当选 Leader 。

Paxos 允许任何节点当选 Leader,只要它在当选后从其他节点获取最新日志即可。Raft 把"日志更新"这个动作前置到了选举阶段------只有日志足够新的节点才有资格当选。这个约束的好处是:选举过程本身不需要交换日志条目,降低了选举的开销。

简化四:日志匹配特性。

Raft 要求日志必须是连续的,Leader 只追加不覆盖。如果 Follower 的日志和 Leader 不一致,Leader 会强制 Follower 复制自己的日志,覆盖冲突的部分。

Paxos 没有这个约束,日志空洞和乱序需要实现者自己处理。Raft 把一致性检查变成了算法本身的规则,而不是实现者的责任。

Raft 和 Paxos 的核心差异

维度 Paxos Raft
Leader 选举 任何节点可当选,当选后同步日志 只有日志最新的节点才能当选
日志结构 允许空洞和乱序 强制连续,Leader 覆盖 Follower
问题分解 组件耦合,难以独立推理 选主、日志复制、安全性三个正交子问题
活锁规避 需要额外的 Leader 选举机制 强 Leader + 随机超时
论文完整性 Multi-Paxos 工程细节缺失 论文完整描述了工程实现

有一篇 2020 年的论文对两者做了深入的对比分析,结论是:Paxos 和 Raft 在共识的核心方法上其实非常相似,唯一的本质差异在 Leader 选举的处理方式上 。

Raft 并没有在算法上"超越" Paxos。它做的是把 Paxos 中那些隐式的、需要实现者自己保证的约束,变成了显式的、算法强制的规则。

为什么工程界选了 Raft

如果 Raft 和 Paxos 在核心方法上相似,为什么工业界几乎一边倒地选择了 Raft?

第一,可理解性带来的工程效率。

一个算法再优雅,如果没人能正确实现,它的工程价值就是有限的。Raft 的论文有完整的状态机描述、清晰的伪代码、明确的安全性证明,工程师照着论文就能实现一个基本正确的版本。Paxos 的论文需要大量额外的解读工作,甚至 Lamport 自己后来专门写了一篇《Paxos Made Simple》来澄清。

有一项用户研究表明,学生学习 Raft 后理解测试的得分明显高于学习 Paxos 的对照组。这不是说 Paxos 更难,而是说 Raft 的呈现方式更友好------论文作者自己承认,"Raft 的可理解性很大程度上来自论文的清晰呈现,而不是算法本身的本质属性"。

第二,生态的飞轮效应。

etcd 选了 Raft,所以 Kubernetes 的选主依赖 Raft。TiKV 选了 Raft,所以 TiDB 的分布式一致性基于 Raft。RocketMQ 的 DLedger 选了 Raft,所以 RocketMQ 的高可用架构依赖 Raft。Kafka 的 KRaft 选了 Raft,所以 Kafka 4.0 移除 ZooKeeper 后基于 Raft。

一旦几个核心项目选择了 Raft,围绕 Raft 的库、教程、最佳实践就会快速积累,形成正反馈。后来的项目在选型时,面对一个成熟的 Raft 生态和一个需要自己踩坑的 Paxos,选择 Raft 是理性的。

第三,Raft 的"不灵活"反而是优势。

Paxos 允许任意节点提出提案,这个灵活性在某些场景下是优势(比如跨地域部署时可以就近提案)。但对大多数系统来说,这个灵活性带来的复杂度远大于收益。Raft 的强 Leader 模型虽然牺牲了灵活性,但换来的是简单、可预测的行为------这对于需要运维和调试的生产系统来说至关重要。

我的理解

说实话,学完 Paxos 再看 Raft,我最大的感受是:Raft 不是什么革命性的算法,它更像是一次精心的"工程化重构"。

Paxos 证明了共识是可以达成的,但它把大量工程决策留给了实现者。Raft 把这些决策变成了算法的一部分:谁当 Leader、日志怎么对齐、选举时检查什么------每一条规则都写清楚了。

这让我想到一个更普遍的规律:在工程领域,"可理解性"往往比"理论优雅"更重要。 一个需要三个月才能理解的算法,即使理论上更优,也很难在团队中推广。一个三天就能上手、文档齐全的算法,即使在某些维度上有所妥协,也更容易成为事实标准。

这不是说 Paxos 不好。Paxos 的理论价值是不可替代的------它定义了共识问题的本质。但如果你要写一个生产系统,Raft 大概率是更好的选择。

结尾

这篇没有深入讲 Raft 的选举安全性证明和日志匹配的具体算法细节。那些内容展开需要很长的篇幅,而且更适合对着论文逐节阅读。如果你对 DLedger 中 Raft 的具体实现细节感兴趣,可以回看上篇关于 DLedger 选主流程和日志复制的内容。

下一篇如果写的话,我想聊聊 Raft 的工程实现中容易被忽略的细节------比如预投票机制、日志快照和成员变更。这些都是论文里有但容易被跳过、而实际实现中必须处理的问题。

适用场景上,如果你在设计一个需要强一致性的分布式系统(注册中心、配置中心、分布式锁、分片调度),Raft 大概率是比 Paxos 更务实的选择。但如果你的团队有深厚的分布式系统经验,或者你的场景需要 Paxos 的灵活性(比如跨地域多活部署),Paxos 的变体仍然值得考虑。

相关推荐
此时不提桶,更待何时2 小时前
06-16-B-Kafka面试与生产事故实战
分布式·面试·kafka
阿里云云原生2 小时前
Kafka 不止于消息:阿里云发布面向 AI 的流算湖一体化实时数据平台
kafka
龙腾-虎跃4 小时前
Docker 一键启动服务合集:Redis、MySQL、Kafka、MinIO、Prometheus 等(网盘转存防失效)
redis·mysql·docker·kafka·prometheus·小龙虾·miniio
此时不提桶,更待何时21 小时前
06-12-A-Kafka存储深水区与源码解析详解
分布式·kafka·linq
此时不提桶,更待何时1 天前
06-15-A-Kafka生态集成与流处理详解
分布式·kafka
做个文艺程序员1 天前
MinIO第05篇:MinIO事件通知机制与Kafka集成——构建SaaS平台的异步文件处理管道
kafka·消息队列·springboot·minio·事件驱动·异步处理
天空鸟_时光不老1 天前
07-检查点与状态持久化
java·人工智能·spring boot·spring·spring cloud·kafka·maven
此时不提桶,更待何时1 天前
06-13-A-Kafka客户端与协议深入详解
分布式·kafka
初见月2 天前
ISR机制保障数据一致性
kafka