3. 选举算法与实现
在第2节中,介绍了在做选举之前做的各服务器之间的通讯初始化。本章将在此基础上,介绍选举的过程。
其大体过程如下:
投票节点:首先将节点状态转变成
LOOKING
状态;投票节点:将自己作为
(SID、ZXID)
广播给其他节点;其他节点:接收其他节点的选举投票;
其他节点:如果接收的选举纪元大于本地的选举轮数则更新本地选举轮数,并将接收的投票跟本地投票比较后更新本地投票,再广播出去。否则执行4;
其他节点:判断外部投票是否优于本地,如果是则更新本地提议再广播出去;
比较纪元大小(最新日志记录的纪元,并不是当前选举纪元);
纪元相等的情况,比较
Zxid
;Zxid
相等的情况下 则比较Sid
;return ((newEpoch > curEpoch) ||
((newEpoch == curEpoch) && ((newZxid > curZxid) || ((newZxid == curZxid) && (newId > curId)))));
投票节点:收集投票提议,并进行统计,若有节点收集的投票大于一半以上则认为该节点为
Leader
节点;投票节点: 若投票选定节点是该节点则转变自己的服务器状态为
LEADING
,若不是则转换成FOLLOWING | OBSERVING
。
1 | public Vote lookForLeader() throws InterruptedException { |
再来详细看下,ZK是按什么判断投票胜出的:
1 | protected boolean totalOrderPredicate(long newId, long newZxid, long newEpoch, long curId, long curZxid, long curEpoch) { |
以上介绍的是整个集群处于启动阶段的选举过程。当集群已经存在一个Leader,而本地机器刚刚进入Leader选举,则会收到其他节点发来的非LOOKING
状态通知:
1 | public Vote lookForLeader() { |