zookeeper原理篇-Zookeeper选举过程分析

Zookeeper的选举算法

zookeeper的选举的大概流程我们知道了,但是我们都知道,选举的过程是基于算法的,zookeeper的选举算法有哪些呢?在zookeeper中,提供了三种Leader选举的算法,分别是LeaderElectionUDP版本的FastLeaderElection以及TCP版本的FastLeaderElection三种选举算法。而选举算法,则是可以在zoo.cfg配置文件中的electionAlg属性来指定,这三种选举算法分别对应值为0-3,其中0为LeaderElection算法,使用的是UDP协议实现,1代表UDP版本的FastLeaderElection算法,这种算法是非授权模式,2代表的也是UDP版本的FastLeaderElection算法,不过这种使用的是授权模式,3代表是TCP协议实现的FastLeaderElection算法。

不过需要注意的是,从Zookeeper3.4.X版本开始,Zookeeper官方已经废弃了UDP协议实现的0-2这三种Leader选举算法,仅仅保留了3这一种TCP协议实现的FastLeaderElection算法,这也是为什么上面我们介绍选举的大致流程中不针对每一种选举算法进行分析的原因。

Leader选举的细节

学习了选举的大概流程以后,我们发现整体流程和算法的设计不难,但是具体如何处理常见的问题的?这个时候我们需要深入细节来学习,首先Zookeeper为了处理不同情况,设计了多个服务端的状态,这个状态的定义在org .apache . zookeeper . server.quorum .QuorumPeer. ServerState 类中,分别如下:

LOOKING:寻找Leader服务的状态,处于当前状态后,将会进行Leader选举流程

FOLLOWING:代表当前服务端处于跟随者状态,表明是Follower服务

LEADING:代表当前服务端处于领导者状态,表明是Leader服务

OBSERVING:观察者状态,表明是Observer服务

前面我们也提到过,每次发出选票后,选票中包含了基本的元素,即ZXID和myid,而这个选票的定义在 apache.zookeeper.server.quorum.Vote类,代码如下:

1.  `finalprivateint version;`

2.  `finalprivatelong id;`

3.  `finalprivatelong zxid;`

4.  `finalprivatelong electionEpoch;`

5.  `finalprivatelong peerEpoch;`

我们把常见的几个属性进行说明,如下:

属性说明
id被选举的SID
zxid当前Leader的事物ID
electionEpoch逻辑时钟,解析出来的,当前处于第几轮选举投票,每次进入新一轮投票后,都会加1
peerEpoch当前被选举的Leader的epoch
state当前服务所处于的状态

学习了这些后,我们来看看选举的通信,前面我们有聊过CilentCnxn是Zookeeper客户端中用于处理I/O网络通信的管理器,而对应的Zookeeper的server中也有一个类–QuorumCnxManager类来接受和处理Leader选举中的通信,而整个过程可以划分几个部分,大致如下:

消息队列处理消息

QuorumCnxManager类中维护了很多队列,用于保存接受到的、等待发送的消息,还定义了消息发送器等,除了接受队列以外,其他的队列都是按照SID分组的集合。其中常见的队列和属性定义如下:

  • recvQueue:消息接受队列,用于存放接受来的所有的消息

  • queueSendMap:消息待发送队列,用于保存等待发送的消息集合,定义为一个Map,按照SID分组设置为key,并且每一个SID对应的都维护了一个队列,保证收发消息互不影响

  • senderWorkMap:发送器集合,每一个senderWork发送器都对应一个远程连接的zookeeper,负责发送消息,在senderWorkMap内部,也是按照SID分组进行维护的。

  • lasteMessageSent:最近发送的消息,在这个集合中,会为每一个SID维护一个最新发送的消息

建立连接

为了能彼此之间通信,zookeeper集群中的实例需要两两建立连接,QuorumCnxManager类在启动的时候会创建一个ServerSokect来监听Leader选举的通信端口,在接受到请求的时候,会调用receiveConnection函数来处理,但是为了避免重复的创建TCP连接,Zookeeper建立了一个规则,只允许SID大的机器往SID小的机器建立连接,当连接连理后,根据远程服务实例的SID创建对应的senderWorker和对应的消息接收器RecvWorker

消息接受和发送

当消息接收器不停的收到消息后,会将其保存在recvQueue队列中,消息发送比较简单,由于每一个SID都有一个维护的独立的SendWorker,只需要不停的从queueSendMap获取要发送的数据进行发送即可,发送完毕后,会将刚刚发送的消息存入lasteMessageSent中,但是需要注意的是,当发现代发送消息的队列是空的时候,就会从lasteMessageSent中获取刚刚发送的消息,然后再次作为消息发送出去,这么设计的原因是为了防止接受方没有收到消息,或者是收到消息后挂了,导致消息没处理完,因为Zookeeper自身对重复消息有处理机制,因此重复发送消息,可以保证能正确处理消息

FastLeaderElection算法

zookeeper的选举网络IO模块我们大致知道了,接下来我们来看看FastLeaderElection选举算法的核心算法实现,流程图如下:

1.自增选举次数

FastLeaderElection的实现中,有一个logicalclock属性,用于标识当前选举的次数,zookeeper要求每次发起选举的时候必须是在同一次选举周期中,因此在每一次选举之前,都会触发logicalclock的自增,达到当前的选举周期

2.初始化选票

前面我们已经知道了选票类的定义在apache.zookeeper.server.quorum.Vote,初始化阶段的时候,每台服务器都会推举自己为Leader,因此都会先初始化一个以自己为主的选票

3.将初始化的选票发送

初始化完选票以后,会将自己的选票信息存入sendQueue队列中,然后用对应每一个SIDworkerSender负责发送出去

4.接受外部投票信息

初始化阶段,除了发送自身的选票信息以外,还会接受来自其他的服务实例发来的选票信息,这些信息存入recvQueue队列中,如果发现无法获取到其他选票信息,就会确认当前服务实例是否和其他的服务实例保持着连接,如果发现连接断开或者是没有连接,则会再次建立连接,当然这里建立连接依然是对比当前服务SID的服务发起连接,防止出现重复创建连接

5.判断选举次数

当发送完初始化选票后,就会开始处理接受来的其他服务实例的选票信息,首先判断接受到的外部投票的选举次数是否大于当前的选票

  • 如果大于当前服务的选票中的选举次数,那么则会更新当前服务的logicalclock,并且清空所有收到的选票,再次拿选票和外部投票进行选票的比较,确定是否真的要更改自身的选票,然后重新发送选票信息。

  • 如果外部选票的选举次数小于当前服务实例的选举次数,那么直接无视掉这个选票信息,并且继续发送自身的选票出去

  • 如果外部选票和自身服务实例的选举次数一致,那么就需要进入选票之间的比较操作

6.选票的比较

选票比较就是整个选举算法的核心逻辑,实现在FastLeaderElection#totalOrderPredicate方法,选票比较主要是为了确定当前服务实例的选票信息是否需要更改以后再次发送新的选票信息,因此会按照选举次数、ZXID和SID来比较:

  • 如果外部投票的选举次数大于当前服务实例的选举次数,就需要投票变更

  • 如果选举轮次一致,那么比较ZXID,如果外部选票的ZXID比较大,需要改变自身服务实例的选票信息

写在最后

很多人感叹“学习无用”,实际上之所以产生无用论,是因为自己想要的与自己所学的匹配不上,这也就意味着自己学得远远不够。无论是学习还是工作,都应该有主动性,所以如果拥有大厂梦,那么就要自己努力去实现它。

最后祝愿各位身体健康,顺利拿到心仪的offer!

由于文章的篇幅有限,所以这次的蚂蚁金服和京东面试题答案整理在了PDF文档里

蚂蚁、京东Java岗4面:原理+索引+底层+分布式+优化等,已拿offer

蚂蚁、京东Java岗4面:原理+索引+底层+分布式+优化等,已拿offer

蚂蚁、京东Java岗4面:原理+索引+底层+分布式+优化等,已拿offer

…(img-E0VuYwdB-1714482075195)]

[外链图片转存中…(img-SnmLPBVw-1714482075196)]

[外链图片转存中…(img-gPqulDtJ-1714482075196)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

  • 16
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Zookeeper是一个分布式应用程序协调服务,它提供了一个分布式锁、分布式队列等基本的分布式协作功能。而Paxos算法则是分布式系统中的一种经典算法,主要用于保证分布式系统的一致性。Zookeeper基于Paxos算法实现了分布式锁和分布式队列等功能。 Paxos算法主要解决的问题是分布式系统中的一致性问题。在分布式系统中,由于网络通信的延迟、节点宕机等原因,可能会导致数据的不一致性。Paxos算法通过选举一个Leader节点来协调各个节点的操作,从而保证系统的一致性。 Paxos算法主要分为三个阶段:提议、批准和执行。在提议阶段,一个节点向其他节点提议一个值;在批准阶段,如果超过半数节点同意了这个值,那么这个值就被批准了;在执行阶段,Leader节点将这个值发送给所有节点,让它们执行。 Zookeeper在实现分布式锁和分布式队列等功能时,也是基于这个流程实现的。当一个进程需要获取锁时,它会向Zookeeper服务发送一个请求,Zookeeper选举一个Leader节点来处理这个请求。当一个进程需要使用队列时,它会向Zookeeper服务发送一个请求,Zookeeper会将这个请求放入队列中,并选举一个Leader节点来执行这个请求。 总之,Zookeeper是一个分布式应用程序协调服务,它提供了一些基本的分布式协作功能。而Paxos算法则是保证分布式系统一致性的经典算法,Zookeeper基于Paxos算法实现了分布式锁和分布式队列等功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值