Raft

71 阅读6分钟

Raft 分布式一致性算法解析

Raft 是一种分布式一致性算法,由 Stanford 大学的 Diego Ongaro 和 John Ousterhout 于 2014 年提出,设计目标是替代 Paxos,解决 Paxos 难以理解和实现的问题。Raft 通过将一致性问题拆解为领袖选举(Leader Election)、日志复制(Log Replication)、安全性(Safety) 三个核心子问题,实现了更简洁、更易工程化的分布式一致性保障。

核心思想

Raft 是一种强领袖(Strong Leader) 算法:

  1. 集群中只有一个领袖(Leader) ,所有写操作必须通过 Leader 完成。
  2. Leader 负责将日志复制到所有跟随者(Follower) ,确保集群状态一致。
  3. 当 Leader 故障时,集群通过选举产生新的 Leader,保证服务不中断。

角色定义

Raft 集群中的节点有三种角色,角色会随集群状态动态切换:

角色职责
领袖(Leader)处理所有客户端写请求,复制日志到 Follower,发起心跳维持领袖地位。
跟随者(Follower)被动接收 Leader 的日志和心跳,不主动发起请求。
候选人(Candidate)当 Follower 超时未收到心跳时,转为 Candidate 发起选举,争取成为 Leader。

关键机制

1. 任期(Term)

Raft 用任期(Term) 来划分时间,每个任期有一个唯一的整数编号(从 0 开始递增)。

  • 任期是集群的逻辑时钟,用于判断节点的新鲜度(旧任期的 Leader 会被新任期的 Leader 取代)。
  • 每个任期对应一次选举:如果选举成功,该任期内有一个 Leader;如果选举失败(如多个 Candidate 分裂投票),则进入下一个任期重新选举。
2. 领袖选举(Leader Election)

选举是 Raft 最核心的机制之一,触发条件是 Follower 超时未收到 Leader 的心跳(超时时间通常为 150-300ms,随机化避免同时发起选举)。

选举流程:

  1. Follower → Candidate:Follower 超时后,自增任期号,转为 Candidate,向所有节点发送 RequestVote RPC(请求投票)。

  2. 投票规则

    1. 节点在一个任期内只能投给一个 Candidate。
    2. Candidate 必须保证自己的日志至少和投票者一样新(日志的最后一条条目的任期号更大,或任期号相同但日志更长)。
  3. Candidate → Leader:如果 Candidate 获得多数节点的投票,则成为 Leader,向所有节点发送心跳(AppendEntries RPC),维持领袖地位。

  4. 选举失败

    1. 如果多个 Candidate 同时发起选举,可能导致分裂投票(无节点获得多数),此时所有 Candidate 超时后自增任期号,重新发起选举。
    2. 如果 Candidate 收到来自新 Leader 的心跳(AppendEntries RPC),则转为 Follower。
3. 日志复制(Log Replication)

Leader 负责将客户端的写请求转换为日志条目,复制到所有 Follower,确保集群状态一致。

日志结构:

  • 每个日志条目包含:任期号(创建该条目的任期)、命令(客户端的写操作,如 set key value)、索引(条目在日志中的位置)。
  • 日志必须满足:相同索引和任期的条目,内容相同;相同索引和任期的条目,之前的所有条目也相同(Leader 保证)。

复制流程:

  1. 客户端请求:客户端向 Leader 发送写请求。
  2. Leader 生成日志条目:Leader 将请求转换为日志条目,追加到自己的日志中。
  3. 发送 AppendEntries RPC:Leader 向所有 Follower 发送 AppendEntries RPC,包含新的日志条目。
  4. Follower 确认:Follower 收到日志条目后,追加到自己的日志中,向 Leader 发送确认(ACK)。
  5. 提交日志:当 Leader 收到多数节点的 ACK 后,标记该日志条目为已提交,并将命令应用到本地状态机,向客户端返回成功。
  6. 同步提交状态:Leader 在后续的心跳或 AppendEntries RPC 中,将已提交的索引告知 Follower,Follower 收到后将该条目应用到本地状态机。
4. 安全性(Safety)

Raft 通过以下规则保证安全性,核心是 “任何时刻,集群中只有一个 Leader,且 Leader 的日志是最新的”

  • 选举安全性:一个任期内只能有一个 Leader。
  • 日志匹配:如果两个节点的日志在某个索引处有相同的任期号,则该索引之前的所有条目都相同。
  • 领袖完整性:Leader 必须包含所有已提交的日志条目(通过投票规则保证,Candidate 必须日志足够新才能当选)。
  • 状态机安全性:如果一个节点将某个日志条目应用到状态机,则其他节点不会在同一索引处应用不同的条目。

关键优化

  1. 日志压缩

    1. 随着时间推移,日志会无限增长,Raft 提供快照(Snapshot) 机制压缩日志。
    2. Leader 将本地状态机的快照发送给 Follower,Follower 用快照替换旧日志,只保留快照后的日志条目。
  2. 增量日志复制

    1. Leader 不需要每次发送完整日志,而是通过 AppendEntries RPC 的 prevLogIndexprevLogTerm 字段,只发送 Follower 缺失的日志条目。
  3. 只读请求优化

    1. 对于只读请求,Leader 可以不写入日志,直接返回结果,但需要先确认自己的领袖地位(如发送心跳确认多数节点在线),避免旧 Leader 处理只读请求。

Raft 与 Paxos 的对比

特性RaftPaxos
设计目标易理解、易实现理论严谨、功能完备
核心思想强领袖,分阶段处理多阶段协商,无固定领袖
工程化难度低(有大量成熟实现,如 etcd)高(难以实现正确的 Paxos)
性能写操作快(强领袖)写操作慢(多阶段协商)

典型应用

Raft 是目前最流行的分布式一致性算法之一,广泛应用于:

  • etcd:Kubernetes 的核心组件,用于配置管理和服务发现。
  • Consul:服务网格和服务发现工具。
  • Redis Cluster(部分特性):Redis 集群的主从复制和故障转移。
  • TiDB:分布式关系型数据库,基于 Raft 实现数据一致性。

总结

Raft 的核心优势是简洁性和可实现性,通过将一致性问题拆解为领袖选举、日志复制、安全性三个子问题,降低了理解和实现的难度。其强领袖设计保证了写操作的性能,而任期和投票规则保证了安全性。对于分布式系统开发者来说,Raft 是必须掌握的一致性算法,也是面试中的高频考点。


是否需要我为你提供Raft 算法的核心 RPC 定义(RequestVote 和 AppendEntries) ,帮助你更深入地理解其通信机制?