引言与背景
分布式系统中,为了在 非拜占庭故障(如节点宕机或网络分区)情况下保持数据一致性,往往需要分布式共识算法来确保多个副本状态统一 。长期以来,Leslie Lamport 提出的 Paxos 算法 一直是这一领域的代表方案,但 Paxos 难以理解和实现,其架构复杂且在实际系统应用中需要很多扩展改动  。为改善这一状况,Stanford 大学的 Diego Ongaro 和 John Ousterhout 在 2013 年提出了 Raft 算法 。Raft 的设计目标是在保证与 Paxos 同等容错能力和性能的前提下,提供更清晰易懂的逻辑结构 。正如 Raft 名称所示(Reliable, Replicated, Redundant, And Fault-Tolerant 的首字母缩写),它旨在构建一个可靠、可复制、冗余且容错的共识方案 。
Raft 算法通过选举产生单一领导者(Leader)来达成共识 。整个系统采用主从复制(单主架构)模式:每个任期(term)内由唯一的 Leader 处理客户端请求,其他节点作为追随者(Follower)复制日志 。Leader 将客户端指令作为日志条目追加,并将其顺序复制到各个 Follower 。Raft 将共识问题分解为 Leader 选举、日志复制和安全性/一致性约束三大子问题分别处理  。这种模块化设计降低了理解难度 。更强的主节点角色也简化了日志管理——例如日志条目只从 Leader 流向 Followers,减少了系统中可能出现的不一致状态 。研究表明,相比 Paxos,学生更容易掌握 Raft 的概念 。Raft 还引入了集群成员变更的新机制,使集群配置变更在不中断服务的情况下安全进行 。如今,Raft 已有多个开源实现,并被 etcd、Consul 等实际系统采用 。
设计目标与核心思想
设计目标: Raft 的首要目标是可理解性。Ongaro 等人在设计 Raft 时,有意避开了 Paxos 晦涩的证明过程和复杂角色分工,而是采用直观的领导者模型和分而治之的方法  。正如作者所言:“我们的主要目标是定义一个实用系统的共识算法,并使其描述显著地比 Paxos 更容易学习” 。因此,Raft 在结构上等价于 Multi-Paxos(在容错性和性能上相当 ),但通过更强的 Leader 机制和状态划分减少了系统可能出现的情况,降低了理解复杂度  。Raft 明确划分出 Leader 选举、日志复制、日志一致性检查等模块,每个模块相对独立 。同时,在 Raft 中 Leader 承担全部日志管理职责,其他节点被动跟随,从而减少了状态的不确定性 。
核心思想: Raft 使用任期(term)概念将时间划分为一个个阶段,每一任期通过选举产生最多一个 Leader  。正常情况下,Leader 一直执掌直到崩溃或失联;此时其余节点通过选举快速产生新的 Leader 接替 。整个过程中遵循以下关键原则以保证一致性 :
• 选举安全:每个任期至多有一名 Leader 当选 。
• 日志一致:Leader 追加日志时不会改写或删除已存在的日志条目,所有日志索引单调增加 。
• 日志匹配:如果两个节点在某索引的日志条目 Term 相同,则在该索引之前的所有日志都相同 。
• 领导者完整性:任期内提交的日志条目,在后续所有任期的 Leader 日志中都会存在 (保证新 Leader 不会丢失已提交条目)。
• 状态机安全:任何已在某节点状态机执行的日志命令,不会在其他节点以不同命令在同一位置执行 。
上述性质通过 Raft 算法的选举和日志复制规则来保障,下文将详细阐述这些机制。
核心机制详解
Raft 的核心机制包括 Leader 选举、日志复制、日志提交以及集群成员变更。下面分别介绍。
Leader 选举机制
Leader 与节点状态: 在 Raft 集群中,节点角色分为三种:Follower(追随者)、Candidate(候选人)和Leader(领导者)。正常运行时集群中只有一个 Leader,其余皆为 Follower 。所有客户端请求统一由 Leader 处理,Follower 则被动接受 Leader 日志并更新状态;若客户端误向 Follower 发请求,Follower 会将其重定向至当前 Leader  。Leader 通过心跳(Heartbeat)消息定期通知 Followers 自己仍存活 。只要 Followers 按期收到心跳,就一直保持在 Follower 状态 。每个 Follower 设置一个选举超时时间(通常在 150~300 毫秒的随机值 ),如果超过该时间未收到 Leader 消息,则认为当前没有 Leader,会转变为 Candidate 发起选举  。
选举流程: 当某节点成为 Candidate,将立即执行以下步骤  :
1. 任期号加一: Candidate 增加本地的当前任期号(currentTerm += 1),表示进入新任期 。
2. 投票给自己: Candidate 给自己投票,并重置选举计时器 。
3. 请求投票: Candidate 向集群中其他所有节点并行发送 RequestVote RPC 请求,内容包括候选人自己的ID、当前任期号,以及候选人最后日志条目的索引和任期等信息  。
4. 等待投票结果: 如果在超时时间内收集到多数(> N/2)节点的投票支持,则选举成功,Candidate 变为 Leader ;如果在等待期间收到某个新Leader的心跳(AppendEntries RPC),则表明其它节点已经选出了 Leader。此时 Candidate 会比较对方任期,与自己相同或更大的则承认败选并退为 Follower ;若对方任期号比自己小则忽略之,继续争取选票 。如果在超时前未出现胜者(可能多个 Candidate 得票分裂),选举宣告失败,各节点进入下一任期并重新发起选举 。
随机超时与选举冲突: Raft 通过随机选举超时避免选票冲突  。Follower 转为 Candidate 的超时时间在一定区间内随机选择,使多数情况下只有一个节点先进入选举并胜出。即便发生并发竞争导致无人过半,所有竞争者都会在再次超时后重新发起选举,而各自新的随机超时将减少再次平票的概率  。这种机制保证了选举很快收敛到某一Leader 。
Leader 就任: 一旦某 Candidate 赢得多数选票成为 Leader,它会立刻更新自己的状态,并向其他节点发送初始心跳以确立自己的领导地位,同时重置其他节点的选举计时器  。之后 Leader 会持续定期发送心跳(即空的 AppendEntries RPC)给 Followers,告知自己存活并阻止新的选举发生  。
日志同步和最新任期校验: 在投票过程中,每个 Follower(即投票者)至多在每个任期投出一票,先到先得 。此外,Follower 会根据候选人的日志情况决定是否投票:只有当候选人的最后日志条目不落后于自己时才会投票给对方  。具体判断依据是比较最后日志的 term 和 index :若候选人日志更新(term 更大,或 term 相同但长度更长),则认为候选人包含了所有已提交的日志,可安全投票支持;反之则拒绝投票  。这一限制称为日志新颖性约束,保证任何当选的 Leader 至少拥有所有已提交日志,从而不会丢失先前任期已经提交(committed)的指令  。若某节点日志落后,则它无法赢得多数选票成为 Leader,这避免了新的 Leader 日志倒退,维护了状态机安全性  。
当追随者等待超过选举超时无收到心跳:
转换状态为 Candidate
currentTerm += 1 // 任期加一
votedFor = self // 投票给自己
votesCount = 1 // (计入自己一票)
重置选举计时器
并行发送 RequestVote(term=currentTerm, candidateId=self,
lastLogIndex, lastLogTerm) 给所有其他服务器
等待投票回复...
if 收到超过半数的 voteGranted:状态 = Leader// 成为Leader后立刻发送初始心跳以宣布领导权for 每个其他服务器:send AppendEntries(term=currentTerm, leaderId=self, prevLogIndex=..., prevLogTerm=..., entries=[], leaderCommit=commitIndex)
else if 收到有效Leader的 AppendEntries:状态 = Follower // 发现他人当选,退为Follower
else if 超时且未获胜:// 平票或无多数,重新发起下一任期选举(保持 Candidate 状态)重新进入上述选举流程
日志复制机制
Leader 选举产生后,集群进入正常运行状态,此时 Leader 开始接收并处理客户端的状态更新请求(通常是一些状态机命令,如键值写入等)。Raft 使用日志(log)来记录这些状态机命令,并通过日志复制来保持各节点状态一致  。
日志条目: 每条日志包含:客户端命令、日志索引(在日志序列中的位置,从1开始编号)以及记录该条目的任期号  。日志索引全局单调递增,而任期号标记了该命令是在集群哪个任期下收到的。日志本质上是 有序的不可变记录,只能在末尾附加条目,不能中途插入或删除(Leader 附加性原则 )。
追加日志流程: 当 Leader 收到客户端请求(例如“在键x写入值y”),它会先将该命令作为一个新的日志条目追加到本地日志尾部  。随后,Leader 会并行地向所有 Follower 发送 AppendEntries RPC 请求,以复制该日志条目 。AppendEntries RPC 除了包含新日志数据外,还带有两个关键参数用于一致性校验:prevLogIndex 和 prevLogTerm,即新条目之前一条日志在 Leader 处的索引和任期 。Follower 收到 AppendEntries 后:
1. 若发现请求中的 term 小于自己的 currentTerm,则拒绝该请求(表明 Leader 过期) 。
2. 否则,检查本地日志是否在 prevLogIndex 处存在一条任期与 prevLogTerm 匹配的日志:如果不匹配,说明Follower日志与Leader出现冲突,则拒绝请求 。
3. 如果 prevLogIndex/Term 匹配,Follower 将 Leader 发来的新条目追加到自己的日志(必要时覆盖冲突部分,详见下一段)  。
4. 若 leaderCommit(Leader发送的已提交索引) 大于 自己的 commitIndex,则更新 commitIndex = min(leaderCommit, 新日志最后索引),表示 Leader 宣布一些日志已经提交  。
5. 向 Leader 返回成功响应。
Leader 维护一个 nextIndex[] 数组记录每个 Follower 下一个需要发送的日志索引 。开始时,Leader 假设 Followers 与自己一致,将 nextIndex 初始化为 Leader 日志最后索引+1 。当某个 Follower 拒绝AppendEntries时(表示日志不一致),Leader 会减小该 Follower 的 nextIndex并重发之前的日志条目,直到找到双方日志的最后一致位置 。一旦一致位置找到,后续 AppendEntries 将覆盖Follower上冲突的条目并追加新条目,使其日志与 Leader 同步 。这个过程实质上删除了Follower上不一致的尾部日志,用 Leader 的日志数据加以取代,从而强制日志一致  。
日志匹配和冲突修正: Raft 依靠上述 prevLogIndex/Term 检查实现日志匹配性(Log Matching) :Leader 在发送新条目时,要求 Follower 上前一条日志必须一致,否则 Follower 拒绝接收。这相当于一个归纳步骤 :确保如果某条目不一致,则不会贸然写入新条目,而是先回退修正直到一致为止。Leader 通过递减 nextIndex,一步步查找日志分歧点,然后删除 Follower 上自分歧点以后的日志 并发送自己这一段的日志条目过去覆盖 。这样做保证了日志前缀一致性:一旦日志在某索引和任期相同,则其之前的部分完全相同 。
值得注意的是,Leader 永远不会覆盖自己日志中的条目,只会在 Follower 上覆盖不一致部分 。因为在正常运行中只有 Leader 接受客户端写入,所以 Leader 日志被视为集群中最完整、最新的权威日志 。Follower 可能因故障错过一些更新,当重新加入时,通过上述机制赶上 Leader 的进度。
心跳与空日志: 当 Leader 暂时没有新的日志条目需要复制时,它仍会周期性发送 AppendEntries 心跳(不携带日志,仅有任期等信息) 。心跳的作用是让 Followers 重置选举超时,防止发起选举,同时携带 Leader 的 commitIndex 等信息以通知 Followers 已提交的日志进度 。
日志提交与应用
提交规则: Raft 要求一条日志在被复制到集群过半数节点后即可认为已提交(Committed) 。Leader 负责跟踪日志复制进度:维护每个节点的 matchIndex(该节点已复制的最后日志索引)。每当发现有一个日志索引 N 满足超过半数节点的 matchIndex ≥ N,且该日志条目的任期是当前任期,则 Leader 将commitIndex推进到 N,表示日志 N 以及之前所有条目都已提交 。这里要求日志任期匹配当前任期是为了确保只有当前 Leader 的日志才能推进提交,避免旧任期日志因为旧 Leader 崩溃后又被提交的情况,保障日志安全性 。一旦 Leader 提交了日志,它就会(在下次心跳中)通知 Followers 最新的 commitIndex 。
状态机应用: 日志提交意味着该指令已经在足够多节点上持久保存,可以保证即使Leader宕机,仍有多数节点保存了该日志,从而一致性达成。此时Leader会将日志条目应用到本地状态机并将结果返回客户端  。Followers 在收到 Leader 通知的提交索引后,也会将尚未应用且已提交的日志顺序地应用到自己的状态机 。这样,集群中所有状态机都会按相同顺序执行相同日志,从而保证状态机一致性 。Raft 确保不会有不一致的应用顺序发生:如果某节点已经在 index=i 执行了日志A,则不可能有另一个节点在同样的 index 执行不同的日志B 。
Leader 损失后的安全性: 日志提交规则配合之前选举中的“日志新颖性约束”,确保了 Raft 的安全性:一条日志一旦在某任期作为已提交出现,则必然存储在之后所有任期的 Leader 的日志中 (Leader 完整性性质)。具体而言,Leader 只有等自己的日志被大多数复制后才标记提交,如果此时 Leader 宕机,由于过半节点已持久该日志,因此任何新的Leader竞选者都必须拥有该日志才能赢得选票  。这样,新Leader的日志一定包含旧Leader提交的所有日志,不会出现提交日志丢失的情况。这一机制保证了日志提交后的一致应用,即使 Leader 切换,先前已提交的日志依然会在后续任期被维持并应用  。
集群成员变更
现实系统中,分布式集群的节点成员可能发生变化,例如新增节点扩容、移除故障节点等。Raft 提供了原生的成员变更机制,使集群配置可以在不中断服务的情况下动态变更,同时确保在变更过程中一致性和安全性不受影响 。
Raft 采用双阶段的“联合共识”(Joint Consensus)方法处理配置变更 。简单来说,在从旧配置 C_old 过渡到新配置 C_new 时,Raft 会引入一个临时配置 C_old,new,该配置包含新老节点的并集 。通过让集群先进入 C_old,new(同时包含所有旧、新节点)并运行一段时间,确保在整个转换过程中任何决策都需要新老两组节点同时参与多数票,从而避免出现两个独立多数派造成脑裂  。转换完成后,再切换到目标的新配置 C_new。
具体流程如下  :
1. 预添加新节点: Leader 在变更配置前,可以先将新节点添加为学习者,把当前日志数据复制给新节点,确保新节点追上现有集群的日志进度 (这一点为了防止直接加入新节点因无日志而拖慢提交)。
2. 进入联合配置: Leader 将联合配置 C_old,new 作为一条特殊配置日志条目写入自己的日志,并像普通日志那样复制到所有旧+新节点  。当这条配置日志被提交(需要旧配置多数+新配置多数都确认)时,集群正式进入联合配置状态 。在 C_old,new 下,集群仍可正常处理日志请求,只是任何日志的提交现在需要在新老两组都达成多数,同步要求更严格。
3. 切换到新配置: Leader 写入新的配置日志条目(仅包含 C_new),并复制到新配置节点集合。当新配置日志提交(此时需要 C_old,new 下多数,即因为两组重叠,多数票自然包含大部分新节点)后,Leader 宣告集群配置切换为 C_new 。此时变更完成,老配置中的被移除节点将不再参与共识。整个过程中集群始终有 Leader (Leader 变更也按老规则进行)并可正常服务读写。
上述方法保证了过渡期间不会出现双Leader或脑裂:因为在联合配置 C_old,new 下,任何有效决策都需要得到新老配置各自多数的重叠认可 。例如从3节点扩容到5节点时,在 C_old,new 阶段需要5个节点中至少3个同意且这3个中至少包含原3节点中的2个,才能提交日志 。这样不可能同时出现原有多数派和新增多数派各自独立做决定的情况 。这个机制等价于一种重叠多数策略,确保配置变化安全平滑 。
需要注意Leader 的特殊职责:配置变更必须由 Leader 发起并在 Leader 日志中形成提交条目,这样变更才能正式生效。期间如果 Leader 宕机,新Leader会根据日志继续未完成的变更过程,保证变更不中断(Raft 论文中也提到了需要处理在配置变更过程中新Leader选举的细节  )。
Raft 的这种成员变更机制相比 Paxos 等方案更为简单实用。例如 Viewstamped Replication (VR) 需要暂停系统或限制请求处理来变更成员,而 Raft 可以在线进行配置变更且不影响正常日志提交 。这也是 Raft 在工程上备受肯定的特性之一。
日志压缩(快照)机制 (补充)
注:日志压缩不在本报告要求范围,但简单提及其存在。随着系统运行,Raft 日志可能无限增长,故 Raft 引入快照(snapshot)机制来压缩日志 。各节点会定期将已经提交且应用过的状态生成快照文件,并丢弃对应的日志条目以节省存储 。Leader 会在有 Follower 落后太多无法通过日志追上时发送快照(InstallSnapshot RPC)进行同步  。快照中记录了状态机状态和最后包含的日志索引、任期等元数据 。通过快照,Raft 保持日志长度可控,同时在快照中包含最新配置以兼容成员变更后的节点同步 。
Raft 与 Paxos 等算法的对比
相对于 Paxos 的优势
可理解性和实现简易度: Paxos 虽然理论成熟,但因其论文和算法描述晦涩,被普遍认为难以理解、难以实现 。相反,Raft 从一开始就以易于理解为设计宗旨 。它采用强领导者模型,将共识流程直观地分解为 Leader 选举和日志复制两个阶段 。Paxos 中的 Leader(Proposer)选举、提案批准等流程在 Raft 中转化为了简单的 RPC 通信和超时机制,降低了心智负担。此外,Raft 将影响正确性的要素全部显式化,例如日志完整性检查、选举限制等规则,都清晰地写入算法和实现  。这使得工程师在实现 Raft 时有明确指引,不像 Paxos 那样留有许多隐含细节需要补全  。正因如此,Raft 的完整特性在论文和技术报告中被描述得相当详尽,包括日志压缩和成员变更等实用功能,而 Paxos 原论文没有覆盖这些工程需求 。总体而言,Raft 更易于教学和实践,这也通过用户研究得到验证:学生在学习Raft后回答相关问题的正确率显著高于 Paxos 。
模块化与状态简单: Paxos 的难点还在于其状态空间复杂,系统可能处于多种微妙的中间状态(多个 Proposer 并行、无Leader等)。Raft 通过限制系统状态来减少这种复杂性。例如,Raft 明确规定每任期至多一个Leader,如果Leader失效则任期结束进入下一任期 。而 Paxos 在一个实例中可能有多个提案竞争,甚至出现活锁需要随机化。这种状态凝聚使 Raft 更易推理。此外,Raft 将共识分解成选举和复制两阶段,使每部分逻辑聚焦单一任务。而经典 Paxos 单个实例只决定一个值,Multi-Paxos 虽可看作连续选举 Leader 进行日志扩展,但概念上没有Raft划分得如此明确。Raft 的随机选举超时机制同样简单有效地解决了 Paxos 中需要额外机制避免冲突的问题 。
性能和一致性保证: 在同步模型和故障模型上,Raft 与 Paxos 本质等价,都属于容忍最多 (N-1)/2 个节点故障的一致性算法,需要多数(quorum)确认才能提交决议 。Raft 作者证明了其结果与 Multi-Paxos 相同且性能相当 。因为Raft 实际上实现了一个长任期内稳定 Leader 的模式,这和 Multi-Paxos没有本质区别 。Raft 每条日志写入也需一次多数确认,和 Paxos 阶段类似。Raft 通过心跳减少空闲时的开销,使保持领导权的成本很小,性能上和 Multi-Paxos 的预选阶段效果接近。另外,Raft 针对实际系统增加的成员变更、日志压缩机制,Paxos 理论上也能做到但要依赖额外算法(如 Vertical Paxos 处理成员变更)。这些在 Raft 中则是内置的特性,使其在工程实用性上更胜一筹 。综上,Raft 没有牺牲性能换取简单——它保持了与 Paxos 同级的效率和容错,同时通过精巧的设计避免了许多复杂情形  。
与其他共识算法的比较
除了 Paxos,Raft 与其他几个著名的一致性算法也有比较:
• Raft vs Viewstamped Replication (VR): VR 是 Oki 和 Liskov 提出的早期主从一致性算法,与 Raft 思路相近(都有 Leader)。Raft 借鉴了 VR 的一些理念,但在成员变更处理上更优雅  。VR 在配置变更时需要暂停服务或采用“双Leader”过渡,Raft 的联合共识无需停服,继续处理日志,更实用 。
• Raft vs ZAB(ZooKeeper Atomic Broadcast): ZAB 是 ZooKeeper 的原子广播协议,也是一种主备日志复制算法。ZAB 偏重于广播消息顺序,它保证全序广播和崩溃恢复。Raft 与 ZAB 在Leader选举和日志同步上机制类似(都有主节点和epoch概念),但 Raft 的选举随机化和日志完整性约束等使得协议证明更加简单。ZAB 没有独立发表为通用算法,其应用主要限于 ZooKeeper,而 Raft 被证明是一个可广泛复用的通用一致性算法,实现也更多样。
• Raft vs Byzantine Fault Tolerance (BFT) 算法: Raft 不考虑拜占庭错误(节点可能作恶),所以不能抵抗恶意节点或数据篡改 。像 PBFT 之类拜占庭容错算法需要 3f+1 节点容忍 f 个恶意节点,开销很大且复杂度高。这类算法应用在需要容忍恶意攻击的场景,如区块链共识。而 Raft 面向常规非拜占庭环境,聚焦于简化实现和高效,在多数企业系统中足够适用且性价比更高。
总的来说,Raft 的出现并非提供革命性的性能提升,而是提供了一种在理解和实现方面极具亲和力的共识算法 。Raft 作者希望“共识算法能被更广泛的受众掌握,并据此构建出更多高质量的分布式系统” 。从目前情况看,这一点很大程度上实现了:Raft 已成为分布式一致性领域的重要里程碑和教学、实践的首选案例。
实际应用案例
Raft 因其清晰的逻辑和可靠性,已被广泛应用于各类分布式系统,下面介绍两个典型案例:
• etcd: 一个流行的分布式键值存储,是 Kubernetes 等系统的关键组件。etcd 内部使用 Raft 实现数据的高可用复制和一致性保证 。整个 etcd 集群由若干节点组成,采用 Raft 来选举产生 Leader,并通过 Leader 将变更日志复制到多数节点提交,从而提供线性一致的读写语义。正因为使用 Raft 共识,etcd 在确保强一致性的同时实现了高可用,当集群中少数节点故障时仍可继续服务。根据 etcd 文档描述:“etcd 使用 Raft 共识算法在成员之间复制请求并达成一致” 。etcd 项目甚至将 Raft 抽象为独立的库(etcd/raft),方便其他项目重用 。实践证明,Raft 支撑下的 etcd 在云环境中能够达到毫秒级的请求延迟和每秒数万次的事务吞吐  。
• Consul: HashiCorp 的开源分布式服务网格和配置系统。Consul 使用 Raft 来管理其内部的服务目录和配置的共享状态。Consul 集群由多个服务器节点组成,其中一个为 Leader,负责接收更新(如服务注册、键值配置变更),通过 Raft 将这些更新日志复制到其他服务器  。Consul 官方文档指出:“Consul 使用一种基于 Raft 的共识协议来提供一致性” 。相比 Paxos,Raft 状态少、算法更易理解,这也是 HashiCorp 选择 Raft 的原因 。Consul 中引入 Raft 后,实现了在数据中心故障或网络分区时仍保持一致的配置存储;只要超过半数服务器存活,Consul 的数据就不会丢失或乱序。同时,Consul 通过 Raft 的 Leader 选举机制来确保只有一个活动 Leader,对外提供服务,这简化了故障切换逻辑。在 Consul 和同门的 Nomad、Vault 等系统中,HashiCorp 都采用了自己用 Go 语言实现的 Raft 库,可见其对 Raft 的信赖  。
除 etcd 和 Consul 外,很多行业系统也纷纷采用 Raft 实现一致性模块。例如:分布式数据库 CockroachDB 将 Raft 用于副本之间的事务日志复制 ;分布式文件系统 SeaweedFS 使用 Raft 管理元数据;消息系统 NATS 的 JetStream 集群模式也基于 Raft 保证元数据和偏移的同步 ;流处理平台 Kafka 在新的 KRaft 模式中甚至用 Raft 取代了原先依赖的 ZooKeeper,实现自身的元数据管理 。这些案例表明,Raft 已成为事实上的分布式一致性实现标准之一,在云原生、微服务、数据库存储等领域发挥着关键作用。
结语
作为一种针对工程可用性优化的共识算法,Raft 在理论与实践之间取得了很好的平衡。它通过清晰的 Leader 模型和模块化分解,使分布式一致性算法不再高不可攀;同时凭借与 Paxos 等效的容错性能,满足了严苛的生产需求。从提出至今的几年里,Raft 已经被深入研究和广泛应用,成为分布式系统课程和教材中的核心内容。在本科教学中引入 Raft,能够帮助学生更直观地理解分布式一致性的要义——如何在不可靠的环境中达成可靠的统一决策。总而言之,Raft 一致性算法以其优雅的设计和强大的实用性,向我们展示了复杂算法可读性的重要价值,也为构建健壮的分布式系统提供了坚实基础。
参考文献:
1. Ongaro, D., & Ousterhout, J. (2014). In Search of an Understandable Consensus Algorithm (Raft).  
2. Raft 官方网站:The Raft Consensus Algorithm.  
3. Wikipedia:Raft (algorithm).  
4. HashiCorp Consul 文档:Consensus Protocol (Raft).  
5. etcd 官方文档:Why etcd – Performance. 
6. 《分布式系统原理与范式》(影射Raft相关章节)  
7. Medium 技术博客:Zhang, Z. Raft Algorithm Explained – Leader Election.   (用于解释随机超时避免冲突)
8. SOFAJRaft 技术文章:Introduction to the Raft algorithm.   (成员变更部分)