三种节点
- follower
- candidate
- leader
- 一般情况下,只有一个leader,其他节点全是follower。
- leader:处理所有的客户端请求(如果一个客户端和follower联系,那follower会把请求重定向给leader)
- follower:不会发送任何请求,只是简单的响应来自leader或者candidate的请求。
- candidate: 选举时期,来描述选举新leader
选举过程
term(任期):有一个follower成为候选人,term+1
集群中只有follower
follower -> candidate
- 这里涉及到了一个选举超时时间,一个追随者在成为候选人之前等待的时间,每个follower被随机分配在150ms和300ms之间。
Raft 使用一种心跳机制来触发领导人选举。一个服务器节点要想继续保持着跟随者状态除非他从领导人或者候选者处接收到有效的 RPCs。
如果一个follower 在一段时间里没有接收到任何消息,也就是选举超时,然后他就会认为系统中没有可用的领导者然后开始进行选举以选出新的领导者。
要开始一次选举过程,跟随者先要增加自己的当前任期号并且转换到候选人状态,并且给自己投一票。然后他会并行的向集群中的其他服务器节点发送请求投票的 RPCs 来给自己投票。
如果接收节点没有在此期间投票,那么这票也算为candidate投票;再发送选票后,重置自己的选举超时时间
Candidate的三种结局
收到大部分选票,成为leader
收到大量同一个任期的选票,保证一个任期号,最多只会有一个领导人被选举出来
一旦候选人赢得选举,他就立即成为领导人。然后他会向其他的服务器发送心跳消息来建立自己的权威并且阻止新的领导人的产生。
其他服务器成为了leader
在等待投票的时候,候选人可能会从其他的服务器接收到声明它是领导人的附加日志项 RPC。如果这个领导人的任期号(包含在此次的 RPC中)不小于候选人当前的任期号,那么候选人会承认领导人合法并回到跟随者状态。 如果此次 RPC 中的任期号比自己小,那么候选人就会拒绝这次的 RPC 并且继续保持候选人状态。
选票瓜分,既没有赢也没有输
意味着有多个跟随者同时成为候选人,而导致无法产生结果。
当这种情况发生的时候,每一个候选人都会超时,然后通过增加当前任期号来开始一轮新的选举。
Raft 算法使用随机选举超时时间的方法来确保很少会发生选票瓜分的情况,就算发生也能很快的解决。为了阻止选票起初就被瓜分,选举超时时间是从一个固定的区间(例如 150-300毫秒)随机选择。这样可以把服务器都分散开以至于在大多数情况下只有一个服务器会选举超时;然后他赢得选举并在其他服务器超时之前发送心跳包。同样的机制被用在选票瓜分的情况下。每一个候选人在开始一次选举的时候会重置一个随机的选举超时时间,然后在超时时间内等待投票的结果;这样减少了在新的选举中另外的选票瓜分的可能性。
这个选举任期将持续到跟随者停止接受心跳并成为候选人。
leader宕机
其他follower在超时期间,未收到心跳包,则重新选举。