Raft/Leader-Election
选举发生
若Follower在指定超时时间内没有收到Leader发送的HeartBeat,则节点状态由Follower转为Candidate.
并开始进行选举.
投票
- CurrentTerm增加1(表示进入下一任期)
- 向自身节点投票
- 设定随机超时时间(ElectionTimeOut -- 2*ElectionTimeOut)
- 向集群中每一个节点发送VoteRequest
- 参数 :
- CurrentTerm : 当前Server CurrentTerm值
- Name : 当前Server名称
- LastLogIndex : Log中最新Index值
- LastLogTerm : Log中最新Term值
处理投票请求
- 判断请求参数Term :
- 如果Req.Term小于Self.Term,拒绝请求并发送Self.Term
- 如果Req.Term大于Self.Term,更新Self.Term并将节点状态转为Follower
- 如果Req.Term等于Self.Term且已经接受过投票,拒绝请求并发送Self.Term
- 判断LastLogIndex,LastLogTerm :
- 如果Self.LastLogIndex 或者 Self.LastLogTerm 大于 Req中相应的值,则拒绝该请求
- 成功投票:
- 更新Self.votedFor为Req.Name
- 流程分析 :
- 判断Term :
- Term为Raft算法中的逻辑时钟.作为某些在同一周期内只能发生一次的行为的判断依据.
- 如果Req.Term大于Self.Term,说明本节点周期落后于系统(新加入集群,Crash后恢复,落后节点等情况)
- 如果Req.Term小于Self.Term,说明请求节点周期落后于系统,则拒绝请求
- 在相同Term周期中,投票行为只能发生一次
- 判断LastLogIndex,LastLogTerm :
- 拒绝投票给Log落后于本节点的节点请求,从而保证选出的Leader拥有最完整的数据
- 因为提交数据需要获得大多数节点的承认,所以落后节点的投票请求会被大多数节点所拒绝,从而保证了Leader一定拥有完整数据.
- 判断Term :
选举结束
- 获得大多数节点同意 : 节点状态从Candidate变为Leader
- 收到AppendEntriesRequest(心跳) : 如果Req.CurrentTerm大于等于Self.CurrentTerm.则节点变为Follower,退出选举.
- 超时 : Self.CurrentTerm增加一.重新开始选举