上一篇我们简单了解了Raft算法,本篇我们来深究Raft的领导者选举机制。
基本流程
前面说到Raft的执行是以一个个的任期为单位的,而一个任期是以投票选举领导者为起点的。
选举领导者的过程:追随者没能收到领导者的心跳包,认为领导者宕机,于是转换为竞选者并发出投票请求(请求投自己一票) --> 其他追随者收到请求,发回选票 --> 竞选者收集选票 --> 选票数量过半,竞选者转换为领导者,选举结束。
如果一切顺利,那么选举领导者就会像上述的流程一样简单。
过半通过
上面提到竞选者的票数过半就可以成为领导者。其实道理很简单,只要有一个竞选者的票数过半,就能保证只选举出一个领导者,避免出现多个领导者。选出了领导者,本任期的第一个阶段就完成了,可以进行响应客户端请求了。
但有没有可能在一轮投票后选不出领导者呢?答案是可能的。例如,竞选者1获得的票数是4,竞选者2的票数也是3,两个竞选者获得的票数是数一数二的,但都没有过半。于是本轮选举失败,本次任期宣告结束。开始新一轮的任期。还记得每一轮的任期首先做什么吗?选举领导者。整个集群会不断尝试选举领导者,直到选出为止。
多个竞选者
在竞选过程中,多个竞选者是怎么出现的?这就不得不提到每个集群节点都有的超时定时器了。
第一个因为没有收到领导者心跳包的追随者会首先成为竞选者,竞选者会向其他节点发出投票请求(这个请求其实也是一个心跳包)。如果其他追随者没能在超时前收到投票请求,就会像第一个成为竞选者的追随者那样认为领导者宕机了,于是转换为竞选者。第二个竞选者就这么出现了。
追随者可以投票给竞选者,竞选者只会投自己一票。所以集群中如果竞选者太多,选票一分摊就很难在本轮选举中选出领导者了。
因此,每个节点超时定时器的初始时间是随机的,且时间不能太短,不然还没等到心跳包发来,追随者就转换成竞选者了。
乐意让贤
第n任领导者(A)由于宕机无法再向追随者发送心跳包,集群的追随者们在等待超时后便开始新一任的领导者选举。之后第n+1任领导者(B)选举出来了。但是如果此时原来的领导者(A)重启成功那岂不是集群中就出现了两个领导者了?其实处理起来很简单:
A领导者向其它成员发送心跳包(任期号是n),其它成员收到,由于它们的任期号是n+1,大于A领导者的任期号,所以不承认它是领导者。
B领导者同样也向其它成员发送心跳包(包括领导者A)(任期号是n+1),领导者A收到后发现这个心跳包的任期号比自己的大,于是让贤退化为追随者,自身任期号更改为n+1。如此一来,整个集群就只有一个领导者了。
参考文章
最后
下一篇会讲解Raft的日志复制机制
对Raft算法感兴趣的朋友还可以阅读一下我翻译的Raft论文