本文已参与「新人创作礼」活动,一起开启掘金创作之路。
定义
raft算法是故障容错算法(Crash Fault Tolerance,CFT)中的一种。
故障容错算法是解决分布式系统中存在存在故障,但不存在恶意攻击场景下的共识问题。
raft允许在n>2f+1(n为节点个数,f为故障节点个数)情况下的分布式共识。
raft算法动画
raft动画算法 可以从raft算法动画了解raft算法
包含流程
raft包含以下流程,后续会逐一详细介绍。
- 初始化
- 选举 Leader Election
- 日志复制 LogReplication
节点状态
- Follower state
- Candidate state
- Leader state
节点角色
不同状态的节点对应不同的角色
- Follower (追随者)
- Candidater (候选者)
- Leader (领导者)
名词解释
term:任期,一个任期内只允许有一个leader。
流程
初始化
所有节点都处于follower state,term为0
选举
选举出主节点
- 所有follower state的follower节点,会启动一个超时计时器随机超时时间为150~300ms,称之为election timeout,选举超时。
- 当超时时间到达,follower节点,会改变状态为candidate state,转变为candidator。
- candidator,变更term任期,term自增,发起leader election。首先投自己一票。然后向其它follower发送投票申请。
- 其它follower收到candidator投票申请后,若当前follower 在term内未投过票,则投candidator一票,返回响应给candidator。并且重置election timeout超时计时器
- candidator收到半数以上投票响应后,转变状态为leader状态,变为leader角色。
- leader会发送定时发送附加条目给所有follower节点,称之为hearebeat timeout心跳检测超时,follower返回心跳检测响应给leader。在未收到心跳检测期间,选举超时计时器就开始计时,收到心跳检测则重置超时计时器。
选举异常情况
- 如果leader宕机,未发送心跳检测,follower 选举超时计时器超时时间到达,就会进行下一轮的选举,follower变成candiate state状态,重复上面的步骤。
- 如果两个follower同时转变成candidate state且未收到半数以上的投票,则继续下一次超时,直到一个follower变成candidate state收到半数以上投票,成为leader
日志复制
通过日志复制,客户端请求操作在系统节点中达到共识。 客户端所有请求都经过leader。由leader转发给follower节点。
- 客户端发送请求给leader,leader将请求操作写入日志,状态为未提交。
- 在下一个心跳检测时,将请求操作转发给其它所有follower节点。
- follower节点接受到请求操作,将操作写入日志,状态为未提交,并返回响应给leader节点。
- leader节点收到半数以上请求,将本地日志提交,并返回客户端结果。同时在下一次心跳将提交请求发送给所有follower节点。
- follower节点收到提交请求将日志提交。系统达到共识
日志复制异常情况
网络分区
假设有5个节点A,B,C,D,E,F。B为leader节点,其它为follower节点。当前term为1
当A和B分与C,D,E网络分区。
A和B,B是leader节点,并持续向A节点发送心跳,无需选举leader节点。
C、D、E由于在超时时间内,未收到leader节点心跳,因此会进行leader election,leader选举,同时term自增+1,term变为2。
假设C、D、E节点中节点E选举为leader节点。在两个分区内分别有一个客户端发送请求到分区内的leader节点。
在A和B分区内,客户端发送请求给leader节点B,B执行操作写入日志,状态为未提交。B将请求发送给分区内其它follower节点A,A节点返回响应,B收到响应,但由于节点个数是5个,B未收到半数以上的响应,因此不会进行提交操作。
而在C、D、E分区节点中,客户端发送请求给leader E,E执行操作写入日志,状态为未提交。E将请求发送给分区其它节点C、D,C、D响应给E,E收到半数以上响应(包括自己),进行提交操作,返回响应给客户端,并发送提交请求给其它节点,其它节点进行提交操作。
当网络恢复后,E和B两个leader节点分别发送心跳给其它所有节点,B和A节点发现更高的term,同步leader E的日志,并回滚自己节点未提交的日志。