概述
1.服务器启动时期的Leader选举。
若进行Leader选举,则至少需要两台机器,这里选取3台机器组成的服务器集群为例。在集群处理阶段,当有一台服务器Server1启动时,其单独无法进行和完成Leader选举,当第二台服务器Server2启动时,此时两台机器可以相互通信,每台机器都试图找到Leader,于是进入Leader选举过程。
(1)每个Server发出一个投票。由于初始情况,Server1和Server2都会将自己作为Leader服务器来进行投票,每次投票会包含所推举的服务器的myid和ZXID,使用(myid,ZXID)来表示,此时Server1的投票为(1,0),Server2的投票为(2,0)然后各自将这个投票发送给集群中其他机器。
(2)接受来自各个服务的投票。集群的每个服务器收到投票后,首先判断该投票的有效性,如检查是否是本轮投票,是否来自LOOKING状态的服务器。
(3)处理投票。
- 优先检查ZXID。ZXID比较大的服务器作为Leader。
- 如果ZXID相同,那么就比较myid。myid较大的服务器作为Leader服务器。
对于Server1,由于Server2的myid最大,于是更新自己的投票为(2,0),然而后重新投票。
(4)统计投票。每次投票后,服务器都会统计投票信息,判断是否已经有过半机器接受相同的投标信息,对于Server1、Server2而言,都统计出集群中已经有两台机器接受了(2,0)的投票信息,此时便认为已经选出了Leader。
(5)改变服务器状态。一旦确定了Leader,每个服务器就会更新自己的状态。
2.服务器运行期间的Leader选举
(1)变更状态,Leader挂后,余下的非Observer服务器都会将自己的服务器状态变更为LOOKING,然后开始进和Leader选举过程。
(2)每个Server会发出一个投票,在运行期间,每个服务器上的ZXID可能不同,此时假设Server1的ZXID为123,Server3的ZXID为122
(3)接收来自各个服务器的投票
(4)处理投票,Server1将夫成为Leader。
(5)统计投票。
(6)改变服务器的状态。
Leader选举算法分析
在3.4.0后的Zookeeper中,只保留了TCP版本的FastLeaderElection选举算法。对于集群中已经存在Leader而言,此种情况一般都是某台机器启动行较晚,在其启动之前,集群已经在正常工作,对这种情况,该机器去选举Leader时,会被告知当前服务器的Leader信息,对于该机器而言,仅仅需要和Leader建立起连接,并进行状态同步即可。
Leader选举实现细节
1.投票数据结构
- id:被推举的Leader的SID
- zxid:被推举的Leader的事务ID
- electionEpoch:逻辑时钟,用来判断多个投票是否在同一轮选举周期中,该值在服务端是一个自增序列,每次进入新一轮的投票后,都会对该值进行加1操作。
- peerEpoch:被推举的Leader的epoch。
- state:当前服务器的状态。
2.QuorumCnxManager:网络IO
每台服务器在启动的过程中,会启动一个QuorumCnxManager,负责各台服务器之间的底层Leader选举过程中的网络通信。
(1)消息队列。QuorumCnxManager内部维护了一系列的队列,除接收队列以外,其他队列都按照SID分组形成队列集合。
- recvQueue:消息接收队列,用于存放那些从其他服务器接收到的消息。
- queueSendMap:消息发送队列,用于保存那些待发送的消息,按SID进行分组。
- senderWorkerMap:发送器集合,每个SenderWorker消息发送器,都对应一台远程Zookeeper服务器,负责消息的发送,也按照SID进行分组。
- lastMessageSent:最近发送过的消息,为每个SID保留最近发送地的一个消息。
(2)建立连接。为了能够相互投票,Zookeeper集群中的所有机器都需要两两建立起网络连接。QuorumCnxManager在启动时会创建一个ServerSocket来监听Leader选举的通信端口(默认3888)。开启监听后,Zookeeper能够不断地接收来自其他服务器的创建连接请求,为了避免两台机器之间重复地创建TCP连接,Zookeeper只允许SID大的服务器主动和其他机器建立连接,否则断开连接。一旦连接建立,就会根据远程服务器的SID来创建相应的消息发送器SendWorker和消息接收器RecvWorker,并启动。
(3)消息接收与发送。在SendWorker中,一旦Zookeeper发现针对当前服务器的消息发送队列为空,那么此时需要从lastMessageSent中取出一个最近发送过的消息来进行再次发送,这是为了解决接收方在消息接收前或者接收到消息后服务器挂了,导致消息未被正确处理。同时,Zookeeper能够保证接收方在处理消息时,会对重复消息进行正确的处理。
最后欢迎大家访问我的个人网站:1024s