Raft算法选举流程及情景分析

Raft算法分为两个阶段

领导者选举

三个角色

Follower、Candidate、Leader(顺序有先后)
三个角色不能越级,即Leader只能退化为Follower、Follower只能升级为Candidate、Candidate可以退化为Follwer、也可以当选成为Leader。(怎么转换的?term、timeout会不会变?)

假设ABC三个节点组成的系统启动之初:
1.假设整个系统启动,也就是没有持久化之前的任何数据(持久化哪些数据),那么三个节点的角色都会被初始化为Follwer,随后开始计算超时时间(该时间为150-200ms随机值),当达到超时时间后,节点转变自己的角色为Candidate,发起RPC请求投票,先来看一下请求投票的参数:
term:发起者此时的term(term?在什么情况下会自增?)
candidateId:发起者的ID
lastLogIndex:当前节点的最新日志(logIndex)的上一条的Index(logIndex-1),理解为下标
lastLogTerm:上述日志对应的term

返回的结果:
term:接受者的term,这个term要注意,是处理完请求后的term,比如你的term比我大请求我投票,那么我返回的将是最新的term,这种情况我认为是用来处理,当一个候选者请求某节点投票,但这个节点已经投给了别人,更新了自己的term且比后来的这个候选者term更大
voteGranted:是否投票,为True证明投票给我

当发起投票后,会有三种可能:
1.候选者收到了超过半数者的同意,成功当选,那么候选者升级为leader,重置自己的超时时间。(有哪些重置自己超时时间的机会?)
2.候选者收到了别人的投票请求,且别人的term比自己的大,那么候选者退化为follower。
3.没有消息,比如网络失败,或者两个人同时发起请求,都没有达到半数,那么将会在达到超时后在此重试,rpc调用失败的情况会直接再次对该节点发起请求。

当候选者把请求发给其他人时,其他人做什么操作呢?
1.有两种情况,会直接拒绝投票:
发起者的Term还没有自己的大,说明发起者早就落后了,这种情况直接拒绝。
发起者和自己的Term相同,但是别人到的早,因为一个Term只能给一个人投票,那么我只有直接拒绝。
还有一种情况是,我发现这个term里我已经投给你了,那么也会返回true,因为可能是上一次的回复消息把消息丢掉了。
2.还有几种情况需要进一步判断
Term相同,且没有投票给别人 或者 别人的Term比自己大,不管我之前投没投过,都要状态转换为follower,且reset超时时间。
这两种情况要进一步判断,上一条log和term的消息。
先去拿到发起者那里上一条logindex和他的term,然后找到自己手里这一条term所对应的term。如果我的term比他的大,那么说明我这里有更新的人当选,如果term相等,就比较log的数量,谁的最新就以谁的为准,如果我的term小于他,说明在他那里有更新的leader产生。

理论依据:1.相同的term和相同的index一定存储一样的数据 2.相同term和相同index之前的数据一定也是相同的
raft算法可以保证在同一个term的数据,一定是只有一个leader给出来的,每一条数据只会创建一个logentry且位置不会再改变。
但是这个位置可能被覆盖,如果还没有提交的话,如果有更大term的leader产生的话,有可能会以此比较发现你这里的log无效,进而把这里给替换掉。
这也就是为什么要比较lastLogIndex和lastLogTerm的原因。

场景分析:
1.ABCDE,A在term1当选leader,虽后DE发生网络分区,但是DE之间无法选出来主,那么他们的term会比较高,那么重新连接网络后,会当选吗?
不会,因为他们的上一个log对应的term比ABC低。
2.前提相同,后来AB发生分区,CDE重新选主,A接受了很多log,然后A不断重启,自身term很大,此时term也大,log也多,能被选吗?不能,原因同上。他的所有log都是在term1接受到的,不可能在高term接到,因为他既然是高term,就不可能是主,非主不接log
3.

ABCDE,A为主,接受了logIndex1,term1,并且同步给其他人,随后crash,但是A再次为主,此时term2,并且又接受了一个logindex2,但是同步给AB后又crash了。
后E为主,在term3当选,为什么是term3,因为BCD里给A投过第二次票,肯定知道目前最新是term2。接到了一个index2,但是没同步,就crash了。为什么能当选,首先term为3,lastLoginIndex是1,在其他人那里term比自己大,index1对应的term也是1,term相同,E的logIndex相等,所以CDE会投票,B不会投,因为log不如她。
然后A又当主了,然后A继续复制logindex2到其他人,此时ABC都复制到了,那么此时index2能标记提交了吗?
不能。因为如果A又crash了,那么E再次当选,为什么再次当选?
因为E的新term为4,且logIndex为2,首先term大,且上一条logIndex对应的term为为#,所以BCDE都会选。
这个时候,logindex2 会覆盖他们,如果之前的term2log被commit
,就会导致数据不一致。
怎么办,不主动去commit,如果crash,没提交就覆盖不会有问题。
如果crash了,但是A当选,term4接了更新的log,在这次同步的时候,会把上一次commit的提交过去,这个时候因为ABC的logIndex更新,所以E不会当选。

数据同步

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理