Zookeeper源码分析
1. Zookeeper源码分析
在QuorumPeerMain的QuorumPeerMain方法中主要做了三件事
2. 单机启动Zookeeper流程
在ZooKeeperServerMain的initializeAndRun(args),其中args就是配置文件中的zoo.cfg的内容
源码如下:
第一步:初始化日志相关配置
第二步:
ServerConfig对象封装了配置文件的内容,后面其他地方可以找该对象拿取
第三步:runFromConfig方法
① 开启metric监控
② 创建FileTxnSnapLog实例和FileSnap实例,并保存刚启动时候的日志数据
③ 启动adminServer
④ 启动NIOServerCnxnFactory
3. Zookeeper集群启动过程
runFromConfig方法
第一步:设置参数
第二步:开启QuorumPeer线程
① run方法:集群的核心方法,进行Leader选举
4. Leader的选举
在集群的核心run方法中,刚开始的是LOOKING状态
进入Leader选举方法中,找接口实现类FastLeaderElection
选举流程:
此方法遍历所有投票参与者集合,将选票信息构成一个ToSend对象,分别发送信息放置到队列sendqueue中,集群中的每一个server节点都会将自己的选票发送给其他server,那么有发送选票,就有接受选票信息,并选出leader
首先我们从队列中选出选票信息,选出的选票信息封装在一个Notification对象中,如果取出的选票为null,我们通过QuorumCnxManager检查发送队列中是否投递过选票,如果投递过说明连接并没有断开,则重新发送选票到其他server,否则说明连接断开,重连所有server即可。连接没有断开,却没有收到选票信息,可能是选票超时,可以将所有选票时限延长一倍。
如果选出的选票Notification不为null,检验投票server和选举leader是否合法,然后根据选票状态执行不同分支,选举过程走LOOKING分支,接下来比较选票epoch和当前逻辑时钟
如果选票epoch大于逻辑时钟,说明选票是新的,自己的选票这一轮已经过时,应该更新当前自己server的逻辑时钟,并清空当前收到的其他server的选票,然后比较自己和选票中谁更适合做leader,发送新的投票给其他所有server
如果选票epoch小于逻辑时钟,zk放弃此次选票,不做任何处理
如果epoch等于逻辑时钟,仍然是比较选票和当前自己的server谁更适合当leader,并重新更新选票,发送给其他所有的server
接下来是将收到的选票放入recvset的map中保存
接下来是判断本轮选举是否结束,如果超过半数的,则leader预选举结束,注意此时还要比较其他少半数选举中有没有谁更适合做leader,如果在选票中找不到一个server比当前server更适合做Leader,则更新server状态,清空recvqueue队列,最终确认选票并返回,否则将更适合做leader的Notification放回队列开始新一轮的选举。
更新状态后,若选票中的服务器状态为FOLLOING或者是LEADING时,其大致步骤会再次判断epoch是否等于逻辑时钟,若等于,再次检查选中的leader过半