《从Paxos到ZooKeeper》第七章总结六:ZooKeeper技术内幕之Leader选举

本文深入探讨ZooKeeper的Leader选举,包括启动时期和运行期间的选举过程,重点解析FastLeaderElection算法,详细阐述选举流程、投票规则及实现细节,如服务器状态、QuorumCnxManager和消息处理等。
摘要由CSDN通过智能技术生成

6 Leader选举

6.1 Leader选举概述

6.1.1 服务器启动时期的Leader选举

触发条件:集群中至少有两台能够互相通信的机器

Leader选举流程:这里以3台为例,当第二台机器Server2启动后,第一、二台机器都试图找到一个Leader,于是进入Leader选举流程:
在这里插入图片描述
在这里插入图片描述

6.1.2 服务器运行期间的Leader选举

Leader如果挂了,则进入新一轮的选举,过程与启动时期的选举基本一致

假设正在运行的服务器有三台:
在这里插入图片描述

6.2 算法分析

介绍FastLeaderElection

6.2.1 术语解释

SID、ZXID、Vote、Quorum
在这里插入图片描述

6.2.2 算法分析
6.2.2.1 进入Leader选举

集群中的一台服务器进入选举的时机:
在这里插入图片描述
一台服务器进入Leader选举时,集群可能的状态:
在这里插入图片描述
如果已经存在Leader:当该机器试图去选举Leader的时候,会被告知当前服务器的Leader信息,然后和Leader服务器建立连接,并进行状态同步即可

如果不存在Leader:开始进行Leader选举,即第一次投票

例子:
在这里插入图片描述

6.2.2.2 开始第一次投票

状态为”LOOKING“,意思是正在寻找Leader;会向集群中所有其他机器发生消息,此消息被称为”投票“

继6.2.2.1例子:
在这里插入图片描述

6.2.2.3 变更投票(第二次投票)

每台机器发出自己的投票后,也会接收到来自集群中其他机器的投票

每台机器会根据一定的规则,来处理收到的其他机器的投票,并以此来决定是否需要变更自己的投票(此规则为算法核心);每次对收到的投票的处理,都是一个对(vote_sid,vote_zxid)和(self_sid,self_zxid)对比的过程

术语:
在这里插入图片描述
4个规则:
在这里插入图片描述
继6.2.2.2例子:
在这里插入图片描述

6.2.2.4 确定Leader

经过第二次投票后,集群中的每台机器会再次收到其他机器的投票,然后开始统计投票

如果一台机器收到了超过半数的相同的投票,那么这个投票对应的SID机器即为Leader

继6.2.2.3中例子:
Server3收到Server3、4、5的相同的投票(3,9),所以Server3成为Leader

6.2.3 总结

哪台服务器上的数据越新,则越有可能成为Leader。

因为数据越新,则ZXID越大,也就越能保证数据的恢复;当然如果ZXID相同,则SID大的当Leader,晚加入,说明机器越新,不容易坏

6.3 实现细节

介绍FastLeaderElection算法实现

6.3.1 服务器状态

SeverState类中列举了4种。分别是LOOKING、FOLLOWING、LEADING、OBSERVING:
在这里插入图片描述

6.3.2 “投票”的数据结构

基本结构如下:
在这里插入图片描述

6.3.3 QuorumCnxManager:网络IO

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

6.3.4 消息队列

QuorumCnxManager内部维护了一系列的队列,用于保存接收到的、待发送的消息,以及消息的发送器

共同点:按SID分组形成队列集合(除了接收队列)

分组概念:如发送队列,假设集群中除自身外还有4台机器,那么当前服务器就会为这4台服务器分别创建一个发送队列,互不干扰,达到隔离的目的

队列类型:
在这里插入图片描述

6.3.5 建立连接

机器需要两两之间建立连接

QuorumCnxManager启动时,会创建一个ServerSocket来监听Leader选举的通信端口(默认3888端口),这样就能不断地接收来自其他服务器的”创建连接“请求;
请求由receiveConnection函数来处理;
为了避免两台机器之间重复创建连接,设计了一种规则:只允许SID大的服务器主动和其他服务器建立连接,否则断开。实现方式为:receiveConnection函数中,服务器通过对比自己和远程服务器的SID值,若自己更大,则断开,然后主动去和远程服务器建立连接(这是一种很好的设计思想)

连接建立成功后,就会根据远程服务器的SID来创建并启动相应的消息发送器SendWorker和消息接受器RecvWorker

6.3.6 消息接收与发送

服务器上每个远程服务器都有其对应的消息发送器SendWorker、消息发送队列和消息接受器RecvWorker、消息接收队列

实现细节:发送消息时,顺便将消息放入LastMessageSent,作为最近发送过的消息;当针对当前远程服务器的消息发送队列为空时,且需要发消息,则从LastMessageSent中取出一个最近发送过的消息来进行发送
此细节解决的一类分布式问题:接收方没有正确处理消息,会要求重传,就是通过LastMessageSent实现的
在这里插入图片描述

6.3.7 FastLeaderElection:选举算法的核心部分

概念:
在这里插入图片描述
选票管理过程中相关组件之间的协作关系:
在这里插入图片描述
算法流程图和文字详解:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
细节:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值