上一篇从零启动了ZK1和ZK2,并且两者投出了ZK2为LEADER,ZK1为FOLLOWER。
然后跳回到了Main loop继续循环,此时ZK1会发现自己的PeerState成了FOLLOWER,ZK2会发现自己的PeerState成了LEADER。
org.apache.zookeeper.server.quorum.QuorumPeer.ServerState#FOLLOWING
ZK1进入org.apache.zookeeper.server.quorum.Follower#followLeader,将自己的状态和地址和端口等告知LEADER,然后读取LEADER的回话。
此时ZK2的循环也发现了自己是LEADER,进入org.apache.zookeeper.server.quorum.Leader#lead,会从new LearnerCnxAcceptor()创建LearnHandler(org.apache.zookeeper.server.quorum.LearnerHandler#run)开始开始往ZK1发送消息并监听其来自FOLLOWER的消息。
LEADER会将EPOCH设置成1,并且在收到ZK1的消息后将该EPOCH返回给ZK1。
ZK1收到来自LEADER的新的EPOCH后,会将自己的EPOCH改成LEADER说的,然后回复一个ACK给LEADER告诉他自己当前的EPOCH/ZXID等。
LEADER收到来自ZK1的ACK后,比对双方的EPOCH/ZXID,然后向ZK1同步最新的数据。
同步完成后,LEADER再向ZK1发送一个最新的ZXID的说明自己是LEADER,ZK1收到后再回复一个ACK。
然后LEADER开始不断循环监听来自ZK1的消息,并分类处理。
然后ZK1开始不断循环监听来自LEADER的消息,并分类处理。
org.apache.zookeeper.server.quorum.Follower#processPacket
messageTracker.trackSent(Leader.LEADERINFO);//1-告知ZK1当前最新的EPOCH
ia.readRecord(ackEpochPacket, "packet");//2-收到ZK1对于EPOCH的ACK
learnerMaster.waitForEpochAck(this.getSid(), ss);//3-校验ZK1发过来的ACK
boolean needSnap = syncFollower(peerLastZxid, learnerMaster);//4-往ZK1同步数据
queuedPackets.add(newLeaderQP);//5-再往ZK1发送一个说我是LEADER
learnerMaster.waitForNewLeaderAck(getSid(), qp.getZxid());//6-等待ZK1再次确认我是LEADER
while (true) {//7-开始不断监听来自FOLLOWER ZK1 的消息
qp = new QuorumPacket();
相关过程在日志上的体现
QuorumServer leaderServer = findLeader();//1-寻找LEADER并获取它的通信地址和相关端口
registerWithLeader(Leader.FOLLOWERINFO);//2-向LEADER获取最新的EPOCH ZXID
syncWithLeader(newEpochZxid);//3-从LEADER同步最新的数据
while (this.isRunning()) {//4-不断监听来自LEADER的消息并分类处理
readPacket(qp);
processPacket(qp);
}
相关过程在日志上的体现
上面已经阅读并观察了节点确定自己的身份后会做些什么。
下一篇阅读,
FOLLOWER收到了需要LEADER执行的命令后,怎么同步给LEADER的,并且LEADER会执行什么操作。
比如,使用zkCli.cmd连接上FOLLOWER,并执行create /test命令。
比如ZK3加入集群,使用zkCli.cmd连接上ZK3,并执行create /test命令后怎么同步给ZK1,是否需要经过LEADER发送?