一、角色划分
- Follower:完全被动,不能发送任何请求,只接受并响应来自leader 和 candidate 的 message,每个节点启动后的初始状态一定是follower;
- Leader:处理所有来自客户端的请求,以及复制 log到所有follower;
- Candidate:用来竞选一个新leader(candidate 由 follower 触发超时而来)
二、Leader选举流程
1、PreVote
一般来说,raft的选举仅且只有一轮投票选出集群leader,但会存在缺陷,就是网络分区后,少数派节点虽然都不会得到足够的票数成为分区Leader,但任选编号term却会不断增加,在网络分区恢复,少数派节点会因为term较大,而迫使多数派Leader下线,我们叫他做捣蛋鬼。为了避免捣蛋鬼谋权篡位,我们引入Pre-Vote,只有得到绝大多数选票,才有被提拔为候选人的资格
在PreVote算法中,Candidate首先要确认自己能赢得集群中大多数节点的投票,这样才会把自己的term增加,然后发起真正的投票,其他投票节点同意发起选举的条件是(同时满足下面两个条件):
- 没有收到有效领导的心跳,至少有一次选举超时
- Candidate的日志足够新(Term更大,或者Term相同raft index更大)
PreVote算法解决了网络分区节点在重新加入时,会中断集群的问题。在PreVote算法中,网络分区节点由于无法获得大部分节点的许可,因此无法增加其Term。然后当它重新加入集群时,它仍然无法递增其Term,因为其他服务器将一直收到来自Leader节点的定期心跳信息。一旦该服务器从领导者接收到心跳,它将返回到Follower状态,Term和Leader一致。
2、Vote
超时驱动:心跳间隔/Leader与followers 间通信超时触发选举的时间
随机的超时时间:降低选举碰撞导致选票被瓜分的概率
选举流程:
- Follower –> Candidate
- 赢得选举:Candidate –> Leader
- 另一个节点赢得选举:Candidate –> Follower
- 一段时间内没有任何节点器赢得选举:Candidate –> Candidate
三、实现时序