Raft算法详解及脑裂
Raft算法
1. 什么是Raft算法呢?
这个算法是一个通过日志复制管理来保证数据一致性的算法。(注意,这个算法保证的一致性不是强一致性,而是最终一致性)
通常发生在集群节点的leader和follower中,通过raft算法的leader选举的leader节点负责管理日志复制过程以实现数据的一致性。
在Raft算法中,有三种节点:
- Leader节点:这个节点是负责管理日志复制和客户端读写请求的节点
- Candidate节点:这个节点是Leader节点的候选节点,经过一个Election timeout后产生的节点
- Follower节点:这个节点是用于处理客户端读请求的节点,同时参与到Leader选举中
Raft的Leader选举可以分为以下几个阶段:
- 我要选举:当在Follower节点的心跳阶段时间内没有收到Leader的响应,就认为Leader节点已经挂了,于是会将自己的term加一同时进行选举。如果在这个阶段接受到了别的节点的选票请求,会对其进行投出自己的选票;如果没有接受到别的请求,会先投自己一票,同时请求别的节点。
- 我要投票:当Follower节点收到投票请求后,会根据以下情况进行决定是否投出自己的选票:
- 发来的投票请求节点的term不能比我小
- 在我当前的term中,我的选票还没有投出去
- 收到多个请求,按先来先得
- 等待响应:当一个candidate发出投票请求后会有三种情况:
- 收到过半的选票,当选Leader节点
- 收到别的节点当选Leader的通知
- 没有收到任何响应,重新发送请求
- 选举阶段:为了保证选举的公平,Raft为每个Follower节点分配了一个随机的Election TimeOut时间,只有过了这个时间才能成为candidate节点
至始至终,Raft算法都是一个一致性算法,是一个AP算法。
2. Raft的脑裂
脑裂是指部署在多个机房中的集群,由于网络的波动,互相感受不到彼此,从而分成多个区间;同时在多个区间进行Leader选举,选举出了各自的Leader节点。
这就是Raft的脑裂。
3.解Raft脑裂
为解决脑裂的产生,Raft使用了一种任期压制机制(Term),只有大的Term才能成为Leader节点。
4. Leader宕机的处理
- 请求到达 Leader 节点之前,Leader 挂了
- 现象:客户端(Client)发送请求,但连接超时或报错。
- 处理:客户端会缓存该请求,并轮询集群中的其他节点。由于此时集群已开始选举,客户端最终会找到新选出的 Leader,并将请求重发给新 Leader。
- 结果:对集群数据无影响,仅增加了请求延迟。
- 未同步之前,Leader 挂了
- 现象:Leader 刚收到请求并写入本地日志(未广播给 Follower),就宕机了。
- 处理:
- 此时该日志条目处于**未提交(Uncommitted)**状态。 新 Leader 产生后,由于它没有这条日志,后续它会强行覆盖旧 Leader 的这条无效日志。
- 结果:该请求被视为执行失败,客户端在重试后会发给新 Leader。
- 同步完成后,Leader 挂了
- 现象:Leader 已将日志同步到多数节点(Quorum),但还没来得及执行 commit(增加本地提交索引)。
- 处理:
- Raft 的选举限制(Election Restriction)确保了新 Leader 必须从那几个已经收到日志的多数派节点中产生。
- 新 Leader 上任后,会发现这条日志虽然未提交,但已存在于多数派中,它会通过发送下一个条目的心跳或日志,间接提交这条之前的日志。
- 结果:数据不会丢失,最终会在新 Leader 的带领下完成提交。
- commit 通知发布后,Leader 挂了
- 现象:Leader 已经提交了日志,并正在给各个 Follower 发送“可以提交”的消息,此时挂了。
- 处理:
- 如果多数派已收到 commit 通知:部分 Follower 已更新状态机。新 Leader 必然拥有此日志,上任后会继续同步 commit 索引。
- 如果仅部分节点收到通知:新 Leader 上任后会发现自己的 commitIndex 较低,但它拥有该日志条目,通过后续的心跳,所有节点最终都会达到一致的提交状态。
- 结果:系统状态保持一致,客户端重试后可以查到该条记录已生效。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Chu_Yu-blog!







