zookeeper中选举leader过程

注:选举leader的过程是参考zookeeper3.3.1.jar


1.名词

选举端口electionAddr:我们知道zookeeper选举时的端口是通过配置文件zoo.cfg配置的,zookeeper将配置文件转换成QuorumServer对象,其中electionAddr属性对应选举端口,对应server.1=registry2.dubbo.host:2888:3888中的3888

zxid:zookeeper 事务id,他是选举过程中能否成为leader的关键因素,它决定当前Server要将自己这一票投给谁(也就是我在选举过程中的value,这只是其中一个,还有id)
ZooKeeper状态的每一次改变, 都对应着一个递增的Transaction id.如果zxid a < zxid b ,则可以保证a一定发生在b之前。这个目前还不太懂(TODO)

myid/id(zookeeper server id): zookeeper server id ,他也是能否成为leader的一个因素。即:集群中某个zookeeper服务端的id(即zoo.cfg配置文件中server.x中的那个x)。代码中的sid也是他。

epoch/logicalclock:他主要用于描述leader是否已经改变,每一个Server中启动都会有一个epoch,初始值为0,当 开始新的一次选举时epoch加1,选举完成时 epoch加1。即每次调用FastLeaderElection.lookForLeader()都加1。


2.对象Quorumpeer、FastLeaderElection、QuorumCnxManager


这三个类处理两类数据:1.sid大的server向sid小的server发送自己的sid 2.(指定情况下)服务器向对方发送自己提议的leader数据
2.1 sid大的server向sid小的server发送自己的sid

数据内容:发送方的id(sid)
目的是与目标服务器建立连接
发送方:QuorumCnxManager.connectOne()
接收方:QuorumCnxManager.Listener线程
过程:
1.QuorumCnxManager.connectOne()发送数据时逻辑:
写入sid
如果自己的id小,就断开连接,什么都不做
如果自己的id>=sid,就启动两个线程SendWorker和RecvWorker用来处理双方通信数据
2.QuorumCnxManager.Listener接收数据时逻辑:
如果自己的id大,就断开连接,并调用connectOne()发送数据
如果自己的id<=sid,就启动两个线程SendWorker和RecvWorker用来处理双方通信数据
2.2(指定情况下)服务器向对方发送自己提议的leader数据

数据内容:发送方提议的leader的sid和zxid
目的:选举出leader
发送方:QuorumCnxManager.RecvWorker和FastLeaderElection.lookForLeader()
接收方:QuorumCnxManager.RecvWorker
过程:
1.接收数据逻辑QuorumCnxManager.RecvWorker
1.接收到数据后放入QuorumCnxManager.recvQueue
2.FastLeaderElection.Messenger.WorkerReceiver取出数据
1.如果对方不是follower(是observer)
则将QuorumPeer.getCurrentVote()作为提议leader放入sendqueue(QuorumCnxManager会发送)
2.如果对方是follower
1.如果当前server的状态是looking
1.将获取到的数据放入recvqueue
2.如果获取数据的server也是looking
取出当前FastLeaderElection提议的id和zxid组装数据,放入sendqueue
2.如果当前server的状态不是looking
1.但是获取数据的状态是looking
取出QuorumPeer.getCurrentVote()的id和zxid组装数据,放入sendqueue(和1不是follower一样)
==>如果对方状态是Looking,则给对方发送我提议的leader,如果自己的状态是looking则接收对方提议的leader数据
2. 3.FastLeaderElection.lookForLeader()选举逻辑
1.logicalclock++
2.更新proposedLeader和proposedZxid
proposedLeader:如果是PARTICIPANT,则取出当前server的id,否则取Long.MIN_VALUE
3.sendNotifications():向所有参与选举的服务器发送数据
ToSend notmsg = new ToSend(ToSend.mType.notification, 
proposedLeader, 
proposedZxid,
   logicalclock,
   QuorumPeer.ServerState.LOOKING,
   sid);
发送数据过程:
sendNotifications()组装数据ToSend放入sendqueue
->WorkerSender取出数据转换成b(ByteBuffer)
->调用QuorumCnxManager.toSend(sid, b)
将数据转换成QuorumCnxManager.Message
放入QuorumCnxManager.queueSendMap.get(sid).put(b)
->QuorumCnxManager.SendWorker发送数据
4.如果当前状态是Looking且stop为true,就一直while循环,循环中
1.取出recvqueue中的数据
recvqueue中数据的来源:???
2.如果取出的recvqueue中的数据是null
就重新发送sendNotifications()或者重新连接manager.connectAll()
3.如果取出的recvqueue中的数据不是null
1.收到的数据state为LOOKING
1.
如果n.epoch > logicalclock,
清空recvset(选举数据???)
更新提议的proposedLeader和proposedZxid
sendNotifications()
如果n.epoch < logicalclock
什么都不做
如果n.epoch == logicalclock,且totalOrderPredicate比较后大于自己的(a pair (server id, zxid) succeeds our current vote)
更新提议的proposedLeader和proposedZxid为收到的数据中的提议
sendNotifications()
2.如果收到的消息的发送者server参与选举
1.recvset.put(n.sid, new Vote(n.leader, n.zxid, n.epoch));
2.如果recvset的长度等于参数选举的总数(收到了返回的所有数据)&&自己提议的leader的权重不为0
设置自己为leader或非其他角色
清空recvset并返回提议的leader
3.通过termPredicate()方法判断自己提议的leader是否已经占大多数
如果循环recvqueue确认没有发生变化(只有我提议的这个是大多数)
则设置自己为leader或非其他角色
清空recvset并返回提议的leader
2.收到的数据state为OBSERVING,
什么都不做,继续循环
3.收到的数据state为LEADING或FOLLOWING
1.如果n.epoch == logicalclock
recvset.put(n.sid, new Vote(n.leader, n.zxid, n.epoch));
如果收到的数据state==leading或者收到的数据的提议已经是大多数termPredicate()
设置自己为leader或非其他角色
清空recvset并返回提议的leader
2.outofelection.put(n.sid, new Vote(n.leader, n.zxid, n.epoch, n.state));
3.如果
termPredicate(outofelection, new Vote(n.leader,n.zxid, n.epoch, n.state))
&& checkLeader(outofelection, n.leader, n.epoch)
logicalclock = n.epoch;
self.setPeerState((n.leader == self.getId()) ? ServerState.LEADING: learningState());















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值