内容出自 : https://www.bilibili.com/video/BV1eL411578r/?spm_id_from=333.337.search-card.all.click
raft具备良好的容错能力,能够在系统出现复杂的故障时依旧能够保证数据的一致性
能够继续对外提供服务
在raft协议中,分布式系统的每个节点有三个状态
跟随者状态
候选者状态
领导者状态
系统中所有的节点都从跟随者开始
如果跟随者没有接收到领导者的消息,那么就会变为候选者状态
当节点成为候选者后,会通过网络消息请求其他节点投票
其他节点接收到投票请求后,会回复投票
候选者节点拿到的投票超过半数时会变成领导者,这个过程就叫做领导选举
随后,系统中所有的事务操作都会通过领导者来操作
假设客户端对分布式节点的数据进行更新.客户端会把写请求发送到分布式节点中的领导者,
领导者会把该事务操作作为一条新的表象,写入到本地日志 注意 这个事务操作只是被添加到日志表象
但并未被提交执行,所以并不会更新节点数据的值
为了提交这个操作,领导者会复制这个事务操作发给所有跟随者状态,此时领导者进入到等待状态,
直到大多数节点将该操作写入到各自本地日志,并且收到这些节点的确认消息,此刻领导者的这个事务操作就
能够真正提交了。随后领导者执行的数据被更新,并且通知所有跟随者这条事务操作已经提交执行,收到消息后跟随者也会提交刚才执行的事务操作,将数据更新。此刻数据的状态就达成一致了。这个流程操作就叫做日志复制
在raft中我们通过设置两个定时器来进行选举,
1.选举计时器(选举计时器的时长控制了一个节点从跟随者等到成为候选者的时间)
选举计时器被随机初始化为150毫秒~300毫秒之前
当一个跟随者节点的选举计时器超时,跟随者就会变成候选者,并且发起一个新德选举周期
周期号位1 term = 1 会给自己投 此时vote count = 1
同时会发送请求给其他节点 发送时会携带节点的周期号(term)
如果接收到消息的节点在这个周期内还没有投过票 就会给这个候选者投票
然后并重启自己的选举计时器,重新执行。一旦该候选者收到了多个节点的赞成票
就会变为领导者,随后领导者会周期性的发送日志增量表象给跟随者,这个也被称为心跳信息
这些增量表象和心跳信息它们的间隔长短由心跳计时器来控制,
跟随者收到增量表象后会回复确认给领导者。这个选举周期会一直持续不变。直到
有某个跟随者在心跳计时器超时之内都没有收到领导者的心跳信息,这个跟随者就会转换为候选者状态
重新发起选举
假设此时有三个节点
node1 node2 node3 node3为leader
此时node3挂了
node1在心跳计时器超时内都没有接收到领导者的心跳信息此时呢会转换为候选者
发起新的一轮选举。 会将投票请求发送给node2 此时node1获得了node2的投票也获得到了自己的
一票 得票数超过半数,此时会变为领导者
但是如果node1 node2同时超时,都会转换为候选者
此时会出现分票问题
raft协议如何处理分票情况呢?
假设node1 node2 node3 node4 4个节点
node1 node2心跳计时器超时 同时变成了候选者状态
并且都发起了投票操作,那么就有可能他俩获取的票数都无法满足半数机制,那么
还会重新发起投票操作,直至选出leader为止
一旦系统中选出了一个领导者 我们需要把之前所有系统中间发生的操作变动复制给所有节点,从而保证所有节点的数据一致性。
这个过程是通过日志增量表象来完成的,日志增量表象同时也用作为节点之间的心跳消息
如果因为网络出现故障 会出现什么情况呢?
node1 node2 node3 node4 node5 node5是领导者
因为网络出现故障部分节点无法通信
node1 node2 nod3成了一组
node4 node5成了一组 并且呢 原leader是node5
那么此时呢 node1 node2 node3会因为接收不到领导者的心跳 然后重新选举出来一个leader(node1)
此刻中网络中就有两个领导者了 并且处于不同的选举(term)周期
假设此时有两个客户端
clientA clientB
clientA像node1发起节点更新操作 更新为3 因为node1这一组呢 拥有多数节点 所以会写入成功
clientB像node5发起节点更新操作 更新为5 node5这一组因为节点没有超过半数,所以写入的数据是
未提交的状态
此刻 两组网络中的节点数据会发生不一致
随后网络故障恢复了 整个分布式系统中出现了两个leader
谁的选举周期高(term)谁就是leader 周期低的会主动变成跟随者
并且会撤回之前没有提交的数据,并将自己的操作日志与新领导的操作日志更新匹配
更新自己的日志数据 从而保证数据的一致性