Zookeeper ZAB协议-Leader&Followe 对象创建和启动源码解析

这篇博客主要是解析了Leader,Follower 对象的创建,相对来说比较简单,主要是了解一下在实例化的时候创建了哪些对象,这些对象会在数据传输的过程中发挥比较打的作用,如果有了解过的,可以直接跳过

因为Zookeeper 启动的一些加载在前一篇文章zookeeper选举流程源码解析 中已经进行解析过了,这里直接从QuorumPeer.run方法开始,在通过快速选举机制选出来Leader,Follower 后会进行相应的对象创建

我们从Leader 开始解析,客户端所有的写操作都是经过leader处理,然后将数据同步给Follower, Observer

QuorumPeer.run.Leading

在确认当前节点为leading节点的时候,会通过

makeLeader 创建leader 对象见QuorumPeer.makeLeader

leader.lead启动见Leader.lead

QuorumPeer.makeLeader

QuorumPeer.makeLeader

Leader.lead

Leader.lead

因为这里只跟主流程,省略了一些代码,防止代码太过繁琐杂乱

1: 会创建一个线程专门处理leader 节点和follower节点socket连接,见LearnerCnxAcceptor

2; 启动Leader Zookeeper, 见 startZkServer

LearnerCnxAcceptor

LearnerCnxAcceptor

LeaderHandler是每一个连接都有一个新建了一个线程处理,和选举的机制相似,在LeaderHandler的run 方法中执行具体的逻辑,见LeaderHandler.run

LeaderHandler#run

LeaderHandler.run

这里只截取了部分代码,可以看到会根据数据的不同类型走不同的逻辑,比如说ping, ack等,具体的代码后续再分析

Leader#startZkServer

startZkServer

zk.startup -> LeaderZooKeeperServer.startup -> ZooKeeperServer.startup , 这里最终会调用到 ZooKeeperServer.startup,见ZooKeeperServer.startup

ZooKeeperServer.startup

ZooKeeperServer.startup

为了让processor 有更直观的影响,这里先展示一下processor 的链式调用图如下

并且因为zk对象是LeaderZookeeperServer,所以setupReuqestProcessors方法会调用LeaderZookeeperServersetupReuqestProcessors方法,见LeaderZookeeperServer#setupReuqestProcessors

LeaderZookeeperServer#setupReuqestProcessors

LeaderZookeeperServer#setupReuqestProcessors

总结一下:

1: 在方法中主要是创建了一系列的Processor 对象

2:commitProcessor, SyncRequestProcessor, PreRequestProcessor这3个对象都是继承与Thread, 直接在这个位置启动了线程,这里稍微在解释一下,因为这3个线程的run 方法中都有从阻塞队列中获取数据,因为这时候还没有和客户端进行交互,这个时候都是处于阻塞的状态,这里的run 方法就不在这里解析了,在和zk 客户端交互的时候再进行解析

好了,LeaderZookeeperServer的启动流程就暂时先介绍到这里,下面说一下Follower 的启动流程

QuorumPeer.run.Following

执行FillowLeader方法见Follower#followLeader

Follower#followLeader

Follower#followLeader

稍微总结一下:

1: 首先是根据投票信息获取leader 节点的对象

2: 和leader 节点建立连接,如果阅读过Leader 节点的创建,应该了解到,在创建leaderServer对象的时候,会创建一个同步数据的socket ss, 然后阻塞在accept 方法上,这里follower 就是和这个socket 对象进行连接, 见 connectToLeader

3: 与leader 进行数据同步,比如说这个节点是新加入的,不存在任何数据,那么需要将之前的数据进行同步,或者某个节点网络分区了,后续重新加入进来,为了保持数据一致性,也需要数据同步,同时也是在这里调用startup 方法启动followerServer的, 见syncWithLeader

4: 死循环接收leader同步数据,就是真正实现处理ZAB 协议的代码

Learner#connectToLeader

connectToLeader

Learner#syncWithLeader

syncWithLeader

这个方法主要是实现了Follower 在启动的时候 和 Leader 数据同步,主要是同步Leader 主节点点中已经执行过,但是Follower 中还不存在的数据, ZK 提供了4种同步方式

  1. DIFF 差异化同步,一般都是Leader 节点事务 > Follower 节点
  2. TRUNC 回滚操作, Follower 节点日志回滚到和Leader 节点一直的情况
  3. TRUNC+DIFF 回滚+同步 一般是Follower 服务器上存在一条事务日志,但是在Leader 上不存在,这种情况出现较少,只有在前leader 节点出现宕机了,然后选举新节点的后才可能发生
  4. SNAP 全量更新,就是集群新加入一个节点,会优先全量同步数据

然后跟leader 节点一样,调用了startup 设置了一些processor,见,startup

ZooKeeperServer.startup

ZooKeeperServer.startup

这里的和Leader 不一样,这里的Server 是FollowerKeeperServer

FollowerKeeperServer#setupRequestProcessors

这里构建的方式也是一样,构建了Processor 链,如下图,同时CommitProcessor, SyncProcessor 都是线程子类,在启动的时候因为队列为空,被阻塞住,不过commitProcess 是调用了wait 方法, 而 SyncProcessor是因为阻塞队列的原因被阻塞住

好了,在这里Follower 启动分析基本完成,有了这些基本储备,我将在下一篇博客根据流程分析一下数据从客户端到服务端操作完成后返回数据的整个流程

posted @ 2022-12-08 11:43  苜蓿椒盐  阅读(90)  评论(0编辑  收藏  举报