raft是paxos算法的一种实现。目标是提供更清晰的逻辑分工使用算法本身更好理解,同时有更高的安全性。Raft能为在计算机集群之间部署有限状态机提供一种通用方法,并确保集群内的任意节点在某种状态转换上保持一致(个人理解就是保证主从的一致性)。
在redis的哨兵模式中就用到了raft协议。
tip:
在raft中每个节点都是有对应的状态的,共3种:
● leader 领袖:负责处理外部信息,并通过心跳机制同步给追随者。
● follower 追随者:转发请求给leader,接收来自leader的心跳
● candidate 候选人:当leader不存在时,进行选举
正常情况下,集群中存在leader和follower,leader会定期给follower发送心跳(heartbeat),以至于让其follower知道还在工作。每个follower会维护一个超时选举器(timeout:150ms或300ms),当在timeout后还未收到leader的心跳,则会成功candidate状态并进行选举;若成功收到了来自leader的心跳,则将timeout清零,重新计数。
当选举开始时,term会+1,表示一个新的任期开始,如果选举成功则正常进行工作;如果失败,则终止当前任期,开启新的任期并开启下一次任期(term+1)
Raft协议主要解决3个问题:
● 领袖选举
● 记录复写
● 安全性
● 起始状态,没有leader
● leader宕机或网络问题
本质都是follower的计时器到期
当集群中有节点的timeout(可能是刚开始,也有可能是宕机了)超时后,则该节点从follower状态变为candidate状态,开始进行选举:追随者将自己的term加1,并为自己投递1票,并向集群中的其他集群发起投票请求。(此时其他节点可能处于follower状态或candidate状态)
当其他节点收到选票请求时,会对选票中的任期信息进行对比,如果选票的任期>自己节点的任期,则会自认落选,并将自己的任期set=选票的任期。如果选票的任期=<自己节点的任期,就意味着在自己已经先于该选票参加过选举了,自己则更应该成功leader
参与选举的节点在timeout时期内会收到来自其他集群的确认消息,如果超过半数都同一成为leader,则真正的成为leader,否则该节点结束当前任期,进入下一任期的选举,term+1;
Raft每个服务器的超时期限是随机的,这降低伺服务同时竞选的几率,也降低因两个竞选人得票都不过半而选举失败的几率。
视频推荐:raft
看一看这个视频,就懂了
个人对任期与选票的理解:
为什么每个节点的timeout不一样是随机的150ms或100ms。
综上:其实只要一个节点的term确定了,那么就暗示着当前的选票就已经投递过了,想要投递新的选票,那么term就必须增加。
即选票的投递一定伴随着term的增加
leader提供写服务,follower提供读服务
在互联网整体来看,读远大于写
当写请求打到leader时,我们必须保证整个集群都能够根据这次写请求达到数据的一致性。
● 当leader收到客户端的请求后,先将修改操作写进自己的日志中,并将日志通过信息随心跳机制发送给其他的follower。自己进入第一阶段
● 其他follower也将此修改操作写到自己的日志中,并回复leader ack。
● 当leader收到半数以上的ack后,给客户端ack,自己本地提交事务,并跟随心跳机制向其他的follower发送提交命令,其他follower收到后,提交本地事务。
网络隔离
● 如图所示,A、B机器与CDE被隔离。leaderb因为无法收到半数以上的ack而重复给其他节点发送信息,CDE因无法收到leader心跳,而进行重新选举,并生成新leaderC。
● 如图,他们节点的任期已经不同了,term高的是最新的数据修改
● 当网络恢复,leaderB会发现新的leader,且其term比自己高,自己会退化为followerB,并回滚自身的日志(未提交部分),followerA也会回滚自己的日志(未提交)。同时BA的term任期变为leader的所属任期(为什么?可以类比人类现实:自己的国家选举了新一届的总统,那自己肯定也必须是新一届的人啊,自己所认识的任期也要与leader一致。另一点保证:下次进行leader选举时,表名自己已经获取到了最新的数据)
● 这样就保证了全局的一致性。
后续………………
● 选举安全性:每个任期最多只能选出一个领袖。
● 领袖附加性:领袖只会把新指令附加(英语:append)在记录尾端,不会改写或删除已有指令。
● 记录符合性:如果某个指令在两个记录中的任期和指令序号一样,则保证序号较小的指令也完全一样。
● 领袖完整性:如果某个指令在某个任期中存储成功,则保证存在于领袖该任期之后的记录中。
● 状态机安全性:如果某服务器在其状态机上执行了某个指令,其他服务器保证不会在同个状态上执行不同的指令。
前四项保证的原因详见上述算法,状态机安全性则借由下述选举流程的限制所达到。
当某台追随者死机时,所有给它的转发指令和拉票的消息都会因没有回应而失败,此时发送端会持续重送。当这台追随者引导重新加入集群,就会收到这些消息,追随者会重新回应,如果转发的指令已经写入,不会重复写入。
领袖死机或断线时,每个已存储指令必定已经写入到过半的服务器中,此时选举流程会让记录最完整的服务器胜选。其中一个因素是Raft候选人拉票时会揭露自己记录最新一笔的信息,如果服务器自己的记录比较新,就不会投票给候选人。(怎么对比最新信息?根据任期和日志?先比任期再比日志?)
因为Raft启动选举是基于超时,使得超时期限的选择至为关键。若遵守算法的时限需求
广播时间 << 超时期限 << 平均故障间隔
就能达到稳定性。这三个时间定义如下:
● 广播时间 是单一服务器发送消息给集群中每台服务器并得到回应的平均时间,需要测量得到。
● 超时期限 是发动选举的超时期限,由部署Raft集群的人选定。
● 平均故障间隔 是服务器发生故障之间的平均时间,可以测量或估计得到。
广播时间典型是 0.5ms 到 20ms,平均故障间隔通常是用周或月来计算的,所以可以将超时期限设在 10ms 到 500ms。