一、背景:为什么需要共识算法?
在分布式系统中,多个节点需要协作完成一项任务(例如存储数据、执行计算),但网络延迟、节点故障、分区等问题可能导致各节点对“系统当前状态”的认知不一致。共识算法(Consensus Algorithm) 的核心目标就是让所有节点对某个值(例如一条日志、一个操作指令)达成一致,从而保证系统的一致性和可靠性。 共识算法需要满足三个核心性质:
- 安全性(Safety) :所有节点最终达成相同的决策结果(例如,不能出现部分节点认为转账成功、另一部分认为失败)。
- 活性(Liveness) :系统最终必须能达成一致(即使部分节点故障,只要多数存活就能继续工作)。
- 容错性(Fault Tolerance) :允许一定数量的节点故障(通常可容忍不超过半数节点宕机)。
共识算法 vs. 其他方案
- 两阶段提交(2PC) :常用于数据库事务,依赖一个协调者(Coordinator),存在单点故障风险。
- 客户端仲裁(Quorum) :读写依赖多数节点响应,但无法处理并发写入冲突。
- 共识算法的优势:在存在节点故障和网络分区的场景下,仍能保证强一致性和系统活性。
为什么需要Raft?
早期的共识算法(如Paxos)虽然功能强大,但因其复杂的理论模型和实现难度,成为许多工程师的“噩梦”。2014年,斯坦福大学的Diego Ongaro和John Ousterhout提出了 Raft算法,其核心理念是通过问题分解和逻辑简化,实现与Paxos同等安全性,同时更易理解和落地。
二、Raft的核心原理:分解问题
Raft将共识问题拆解为三个独立的子问题,并通过清晰的规则组合解决:
1. 领导选举(Leader Election)
- 问题:分布式系统需要唯一的领导者(Leader)来协调所有操作,避免多节点同时决策导致冲突。
- Raft的解法:
- 任期(Term)机制:全局单调递增的编号(类似“朝代”),每个任期内至多一个Leader。
- 心跳(Heartbeat)驱动选举:节点默认是Follower,若超时未收到Leader心跳,则发起选举成为Candidate,向其他节点拉票。
- 多数派原则:Candidate需获得超过半数的选票才能成为Leader。若选举超时,则开启新任期重新选举。
2. 日志复制(Log Replication)
- 问题:Leader需要将客户端的操作以日志形式复制到所有节点,并确保最终一致。
- Raft的解法:
- 顺序追加日志:Leader将客户端请求按顺序写入本地日志,然后并行通知其他节点复制。
- 一致性检查:Follower收到日志后,会检查其任期和索引是否与Leader匹配,否则拒绝接收。
- 提交(Commit)规则:当日志被复制到多数节点时,Leader将其标记为“已提交”并应用到状态机,随后通知所有节点提交。
3. 安全性(Safety)
- 问题:保证系统在极端情况(如Leader宕机、网络分区)下仍能正确运行。
- Raft的解法:
- 选举限制:只有拥有最新日志的Candidate才能当选Leader,避免数据回滚。
- 提交旧任期日志的限制:Leader只能提交当前任期的日志,间接提交旧任期的日志,避免已提交的日志被覆盖。
三、Raft的关键设计亮点
-
强领导者模型:
Leader负责所有决策(如日志复制、提交),Follower只能被动响应。这种设计简化了节点间的交互逻辑。 -
可理解的术语:
Raft用“任期(Term)”“日志索引(Log Index)”等直观概念取代Paxos的抽象术语,降低了理解门槛。 -
多数派(Quorum)原则:
无论是选举还是日志提交,均需超过半数节点同意。这一原则天然容忍少数节点故障,同时保证系统活性。
四、Raft的应用场景
- 分布式数据库:如etcd、TiDB使用Raft实现数据多副本一致性。
- 服务发现与协调:Consul、Apache ZooKeeper依赖Raft维护集群状态。
- 区块链与容器编排:Kubernetes的kubeadm模式、部分联盟链采用Raft作为共识层。
五、学习Raft的推荐资料
-
论文与官方资源:
-
可视化工具:
- Raft动画演示 - 通过交互动画理解Raft运行流程。
-
代码实现:
- Hashicorp Raft(Go语言) - 生产级Raft库。
- etcd Raft模块(Go语言) - 高性能实现。