最近看了一下mit 6.824的课程,完成了Raft Part A的实验,在这里做一个简单的记录
Part A: Leader election
1. Leader 选举流程
(1)所有成员的状态共分成三种: leader, follower, candidate, 初始化状态为follower
(2) 程序启动之后,server 在等待选举超时时间(electionTimeout)之后,没有接受到来自leader 发送的心跳(ApppendEntriesRequest, 而且自身不是leader, 则发起选举流程
(3)选举开始时, follower 将自身的状态设置成candidate, 同时自身的term 加1,将自己的选票数量设置成1(自己为自己投一票), 往其他的成员发送RequestVote 请求; 其他成员收到请求后,如果对方的term大于自身,且自身的在这一term没有投过票,则将票投给对方,否则拒绝,并将自身的状态设置成follower, 放弃竞选。
(4)为了防止一个集群出现两个leader,集群中成员的数量n必须是单数,任意一个成员必须收到超过成员数量一半以上的选票,才算竞选成功。
(5)竞选成功后的leader, 定期向所有成员发送心跳,更新其余成员的状态。同时避免别的成员因为收不到心跳而发起新的请求。
2. 注意事项:
(1) 如何避免平分选票,比如3个成员,总是同时发起选举,都给自己投了一票,那么永远选不出leader。解决方法:每个成员初始启动,或者每次发起选举时,为自己的electionTimeout 设置一个随机值(400ms ~ 600ms 之间,lab中参考值)。 这样成员不会同时发起选举,随机到比较小的electionTimeout的成员往往优先发起选举, 进而赢得竞选。
(2)candidate 收到AppendEntries时,如果appendArgs 中term大于本身Term, 那么candidate自动转换成follower,放弃选举
(3) Leader 挂了之后,再次复活,发送AppendEntries时, term 落后,自动转换成follower
(4)选举的leader 必须拥有所有已经提交的entry,日志安全性
心跳时间(heartbeatTime) << 选举超时时间(electionTimeout) << 平均故障间隔时间(MTBF)