ZooKeeper之Leader选举

        Leader选举是ZooKeeper中最重要的技术之一,也是保证分布式数据一致性的关键所在。

1.leader选举

         Leader选举主要分为服务器启动时期的Leader选举和服务器运行期间的Leader选举。以下是两种情况的选举大致步骤。

服务器启动时期的Leader选举

1.每个Server会发出一个投票:投票包含要选举的服务器的SID和ZXID等信息,将这个投票发送给集群中其它所有机器。

2.接收来自各个服务器的投票:每个服务器都会接收来自其它服务器的投票。集群中的每个服务器在接收到投票后,首先会判断该投票的有效性,包括检查是否是本轮投票、是否来自LOOKING状态的服务器。

3.处理投票:在收到来自其它服务器的有效投票后,针对每一个投票,服务器都需要将别人的投票和自己的投票按规则进行投票。

4.统计投票:每次投票后,服务器都会统计所有投票,判断是否已经有过半的及其接收到相同的投票信息,确认Leader。

5.改变服务器状态:一旦确定了Leader,每个服务器就会更新自己的状态:如果是Follower,那么就变更为FOLLOWING,如果是Leader,就变更为LEADING。

 

服务器运行期间的Leader选举

        这种情况只有在原有的Leader服务器挂了,才会进入新一轮的选举。大致流程如下:

1.变更状态:当Leader挂了之后,余下的非Observer服务器(Observer服务器不参与投票,Observer服务器的主要作用就是为了缓解读的压力)都会将自己的服务器状态变更为LOOKING,然后开始进入Leader选举流程。

2.每个Server会发出一个投票。

3.接收来自各个服务器的投票。

4.处理投票。

5.统计投票。

6.改变服务器状态。

        观察上面两种情况的流程可以看出,两者就是第一步存在不同,运行期间进入选举,需要进行状态的变更。

 

2.Leader选举的算法分析与具体实现

        Leader选举算法主要是PK阶段的实现。因为投票信息包含了两个最基本的信息:推选的服务器的SID和ZXID,分别代表了被推选服务器的唯一标识和最新事务ID.当集群中每台机器发出自己的投票后,也会接收到来自集群中其它机器的投票。每次对于收到的投票的处理。

1.如果接收到的投票的ZXID大于当前机器的ZXID,则将接收到的投票变更成自己的投票再次发出去。

2.如果接收到的投票的ZXID小于当前机器的ZXID,不作任何变更。

3.如果两者的ZXID相等,则选择SID大的作为Leader。

        以上是Leader选举算法的核心规则,以下便是该算法在ZooKeeper中是如何实现的。

         首先,先了解一下服务器的几个状态:

LOOKING:寻找Leader状态。

FOLLOWING:跟随者状态,表明当前服务器角色是Follower

LEADING:领导者状态,表明当前服务器角色是Leader。

OBSERVING:观察者状态,表明当前服务器角色是Observer。

        在Leader选举过程中,QuorumCnxManager负责各台服务器之间的底层Leader选举过程中的网络通信。每台服务器启动的时候,都会启动一个QuorumCnxManager。

消息队列

        QuorumCnxManager内部维护了一系列的队列和集合。

recvQueue:消息接收队列,用于存放那些从其它服务器接收的消息。

queueSendMap:消息发送队列,是一个Map,key为服务器的SID,值分别为SID对应的机器分配的一个单独队列。

senderWorkerMap:发送器集合。key为服务器的SID,值为每个服务器对应的SendWorker消息发送器。

lastMessageSent:最近发送过的消息集合,这个集合为每个SID保留最近发送过的一个消息。

消息接收与发送

        首先ZooKeeper集群中的所有机器需要两两建立起网络连接。开启端口监听后,ZooKeeper就不断地接收到来自其它服务器的"创建连接"请求,在接收到其它服务器的TCP连接请求时,会交由receiveConnection函数来处理。为了避免两台机器之间重复地创建TCP连接,ZooKeeper设计了一种TCP连接的规则:只允许SID大的服务器主动和其它服务器建立连接,否则断开连接。建立起连接之后,就会根据远程服务器的SID来创建相应的消息发送器SendWorker和消息接收器RecvWorker,并启动他们。

        ZooKeeper会为每个远程服务器分配一个RecvWorker,而每个RecvWorker从这个TCP链接中读取消息,并将其保存到recvQueue队列中。同时,ZooKeeper为每个远程服务器单独分配了消息发送器SendWorker,每个SendWorker不断地从对应的消息发送队列中获取出一个消息发送,并将这个消息放入lastMessageSent中来作为最近发送过的消息。注意:如果ZooKeeper发现针对当前远程服务器的消息发送队列为空,那么这个时候需要从lastMessageSent中取出一个最近发送过的消息来进行再次发送。

        而进行选举的核心算法是基于TCP的FastLeaderElection算法。WorkerReceiver不断地从QuorumCnxManager中获取出其它服务器发来的选举消息,并将其转换成一个选票,然后保存到recvqueue队列中去。在选票的接收过程中,如果发现该外部投票的接收过程中,如果发现该外部投票的选举轮次小于当前服务器,就直接忽略这个外部投票,同时立即发出自己的内部投票;当前服务器不是LOOKING状态,忽略这个外部投票,将Leader信息以投票的形式发送出去;如果接收到的消息来自Observer服务器,就忽略该消息,并把自己当前的投票发送出去。而WorkerSender会不断地从sendqueue队列中获取待发送的选票,并将其传递到底层QuorumCnxManager中去。然后根据对应的接收到的选票按照规则进行处理,直到选出Leader。

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值