zookeeper - 选举(2)

本文涉及的产品
任务调度 XXL-JOB 版免费试用,400 元额度,开发版规格
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
云原生网关 MSE Higress,422元/月
简介: 概述    zookeeper核心知识点之一就是集群之间的选举,而且很多文章都把选举跟paxos进行对比,其实我觉得选举过程其实跟paxos没什么关系(的Paxos算法和zookeeper的关系)。

概述

    zookeeper核心知识点之一就是集群之间的选举,而且很多文章都把选举跟paxos进行对比,其实我觉得选举过程其实跟paxos没什么关系(的Paxos算法和zookeeper的关系)。

    网上关于zookeeper的选举过程的文章其实挺多的,所以会借鉴很多其他人的文章,整体思路按照以下顺序进行介绍:1、选举的网络连接(着重介绍选举的组网);2、选举功能设计(着重介绍QuorumPeer内部的设计);3、选举的报文格式(介绍报文格式);4、选举逻辑处理(介绍选举的逻辑处理)

    最后参考文档中的几篇文章感觉都非常有特色,如果有什么不是特别明白的可以直接参考

  Zookeeper的Leader选举》文章,讲的非常非常非常详细。我的这篇文章额外的将对应的代码逻辑截图。


选举网络连接

        server.0=192.168.192.128:2888:3888

        server.1=192.168.192.129:2888:3888

        server.2=192.168.192.130:2888:3888

    集群模式下我们一般都会配置上面的集群地址,配置中有两个TCP port。后面一个是用于Zookeeper选举用的,而前一个是Leader和Follower或Observer交换数据使用的。我们还注意到server.后面的数字。这个就是myid。

img_8890288e30ab2eafef9d4e8d0883ce58.png
不同端口的使用情况

    在整个选举过程中由myid大的向myid小的server发起连接,在tcp连接中包括client/server端,对应到zk的集群连接当中,myid大作为client端,myid小作为server端。也就是说server.2会主动去连接server.1和server.0,server.1会主动去连接server.0。

    不要因为上面的描述就以为server之间没有两两建立连接,其实连接都是两两之间建立的,只不过一个作为发起者一个作为接受者而已,两者之间都是保持连接的。


选举功能设计


QuorumCnxManager

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

    (1) 消息队列。QuorumCnxManager内部维护了一系列的队列,用来保存接收到的、待发送的消息以及消息的发送器,除接收队列以外,其他队列都按照SID分组形成队列集合,如一个集群中除了自身还有3台机器,那么就会为这3台机器分别创建一个发送队列,互不干扰。

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

        · queueSendMap:消息发送队列,用于保存那些待发送的消息,按照SID进行分组。

        · senderWorkerMap:发送器集合,每个SenderWorker消息发送器,都对应一台远程Zookeeper服务器,负责消息的发送,也按照SID进行分组。

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

    (2) 建立连接。为了能够相互投票,Zookeeper集群中的所有机器都需要两两建立起网络连接。QuorumCnxManager在启动时会创建一个ServerSocket来监听Leader选举的通信端口(默认为3888)。开启监听后,Zookeeper能够不断地接收到来自其他服务器的创建连接请求,在接收到其他服务器的TCP连接请求时,会进行处理。为了避免两台机器之间重复地创建TCP连接,Zookeeper只允许SID大的服务器主动和其他机器建立连接,否则断开连接。在接收到创建连接请求后,服务器通过对比自己和远程服务器的SID值来判断是否接收连接请求,如果当前服务器发现自己的SID更大,那么会断开当前连接,然后自己主动和远程服务器建立连接。一旦连接建立,就会根据远程服务器的SID来创建相应的消息发送器SendWorker和消息接收器RecvWorker,并启动。

    (3) 消息接收与发送消息接收:由消息接收器RecvWorker负责,由于Zookeeper为每个远程服务器都分配一个单独的RecvWorker,因此,每个RecvWorker只需要不断地从这个TCP连接中读取消息,并将其保存到recvQueue队列中。消息发送:由于Zookeeper为每个远程服务器都分配一个单独的SendWorker,因此,每个SendWorker只需要不断地从对应的消息发送队列中获取出一个消息发送即可,同时将这个消息放入lastMessageSent中。在SendWorker中,一旦Zookeeper发现针对当前服务器的消息发送队列为空,那么此时需要从lastMessageSent中取出一个最近发送过的消息来进行再次发送,这是为了解决接收方在消息接收前或者接收到消息后服务器挂了,导致消息尚未被正确处理。同时,Zookeeper能够保证接收方在处理消息时,会对重复消息进行正确的处理。


FastLeaderElection:选举算法核心

    选票管理

        · sendqueue:选票发送队列,用于保存待发送的选票。

        · recvqueue:选票接收队列,用于保存接收到的外部投票。

        · WorkerReceiver:选票接收器。其会不断地从QuorumCnxManager中获取其他服务器发来的选举消息,并将其转换成一个选票,然后保存到recvqueue中,在选票接收过程中,如果发现该外部选票的选举轮次小于当前服务器的,那么忽略该外部投票,同时立即发送自己的内部投票。

        · WorkerSender:选票发送器,不断地从sendqueue中获取待发送的选票,并将其传递到底层QuorumCnxManager中。


架构图和源码

img_54965ee22655d57ab7af0b0146715a68.png
选举整体设计


img_3a3c484fce25bec51b65c99a7cc60c5b.png
QuorumCnxManager对象


img_32cdc2ab654b8ec34b5d5b3edfde4e83.png
FastLeaderElection设计


选举报文格式

leader:被推举的leader,zxid被推举的事务,peerEpoch被推举的轮次,electionEpoch推举服务器轮次,state推举服务器的状态,sid是接收消息的服务器sid。


img_e12eafe570eeba79ddac89581c10e442.png
消息报文格式


img_3a809be4800962f2d1cbf81b4bd5fa45.png
发送报文格式


img_aa58692f1d1af963bbcf686c33b24c95.png
接收报文格式


选举逻辑处理

Leader选举的基本流程如下

1. 自增选举轮次。Zookeeper规定所有有效的投票都必须在同一轮次中,在开始新一轮投票时,会首先对logicalclock进行自增操作。

2. 初始化选票。在开始进行新一轮投票之前,每个服务器都会初始化自身的选票,并且在初始化阶段,每台服务器都会将自己推举为Leader。

3. 发送初始化选票。完成选票的初始化后,服务器就会发起第一次投票。Zookeeper会将刚刚初始化好的选票放入sendqueue中,由发送器WorkerSender负责发送出去。

4. 接收外部投票。每台服务器会不断地从recvqueue队列中获取外部选票。如果服务器发现无法获取到任何外部投票,那么就会立即确认自己是否和集群中其他服务器保持着有效的连接,如果没有连接,则马上建立连接,如果已经建立了连接,则再次发送自己当前的内部投票。

 5. 判断选举轮次。在发送完初始化选票之后,接着开始处理外部投票。在处理外部投票时,会根据选举轮次来进行不同的处理。

· 外部投票的选举轮次大于内部投票。若服务器自身的选举轮次落后于该外部投票对应服务器的选举轮次,那么就会立即更新自己的选举轮次(logicalclock),并且清空所有已经收到的投票,然后使用初始化的投票来进行PK以确定是否变更内部投票。最终再将内部投票发送出去。

· 外部投票的选举轮次小于内部投。若服务器接收的外选票的选举轮次落后于自身的选举轮次,那么Zookeeper就会直接忽略该外部投票,不做任何处理,并返回步骤4。

· 外部投票的选举轮次等于内部投票。此时可以开始进行选票PK。

6. 选票PK。在进行选票PK时,符合任意一个条件就需要变更投票。

 · 若外部投票中推举的Leader服务器的选举轮次大于内部投票,那么需要变更投票。

 · 若选举轮次一致,那么就对比两者的ZXID,若外部投票的ZXID大,那么需要变更投票。

 · 若两者的ZXID一致,那么就对比两者的SID,若外部投票的SID大,那么就需要变更投票。

7. 变更投票。经过PK后,若确定了外部投票优于内部投票,那么就变更投票,即使用外部投票的选票信息来覆盖内部投票,变更完成后,再次将这个变更后的内部投票发送出去。

8. 选票归档。无论是否变更了投票,都会将刚刚收到的那份外部投票放入选票集合recvset中进行归档。recvset用于记录当前服务器在本轮次的Leader选举中收到的所有外部投票(按照服务队的SID区别,如{(1, vote1), (2, vote2)...})。

9. 统计投票。完成选票归档后,就可以开始统计投票,统计投票是为了统计集群中是否已经有过半的服务器认可了当前的内部投票,如果确定已经有过半服务器认可了该投票,则终止投票。否则返回步骤4。

10. 更新服务器状态。若已经确定可以终止投票,那么就开始更新服务器状态,服务器首选判断当前被过半服务器认可的投票所对应的Leader服务器是否是自己,若是自己,则将自己的服务器状态更新为LEADING,若不是,则根据具体情况来确定自己是FOLLOWING或是OBSERVING。

  以上10个步骤就是FastLeaderElection的核心,其中步骤4-9会经过几轮循环,直到有Leader选举产生。



img_32269afc78b0d4202c3b010d5f25d1c3.png
选举投票-1


img_37c08596b7062aed7d31cdfe0c4ae34e.png
选举投票-2


img_dc59c379258f7cd0eb9db41336a2c134.png
选举投票-3


img_b850691b8b09094f19336ad8eaf4cc7d.png
选举投票-4


参考文档

    Zookeeper的Leader选举

    ZooKeeper之FastLeaderElection算法详解

    zookeeper-服务器启动

    Paxos算法和zookeeper的关系

相关实践学习
基于MSE实现微服务的全链路灰度
通过本场景的实验操作,您将了解并实现在线业务的微服务全链路灰度能力。
目录
相关文章
|
9月前
|
存储 负载均衡 算法
深入浅出Zookeeper源码(七):Leader选举
对于一个分布式集群来说,保证数据写入一致性最简单的方式就是依靠一个节点来调度和管理其他节点。在分布式系统中我们一般称其为Leader。
217 6
|
9月前
|
消息中间件 分布式计算 算法
深入理解Zookeeper系列-3.Zookeeper实现原理及Leader选举源码分析(上)
深入理解Zookeeper系列-3.Zookeeper实现原理及Leader选举源码分析
719 0
|
存储 算法 Java
准备跳槽必看的这道【Java面试题】:谈谈你对Zookeeper 选举原理的理解
一位工作了 7 年的程序员,最近在面试时被问到一个关于Zookeeper的问题。因为平时很少研究,所以面试的时候只能一直说:不知道,不知道,不知道。当时,他感觉很尴尬,面试还没结束,就已经知道应该被Pass了。于是又来问我,希望我能分享一期这样的视频。
116 2
|
数据安全/隐私保护
Zookeeper快速入门(Zookeeper概述、安装、集群安装、选举机制、命令行操作、节点类型、监听器原理)(二)
Zookeeper快速入门(Zookeeper概述、安装、集群安装、选举机制、命令行操作、节点类型、监听器原理)(二)
|
4月前
|
分布式计算 负载均衡 算法
Hadoop-31 ZooKeeper 内部原理 简述Leader选举 ZAB协议 一致性
Hadoop-31 ZooKeeper 内部原理 简述Leader选举 ZAB协议 一致性
57 1
|
5月前
|
存储 负载均衡 算法
分布式-Zookeeper-Master选举
分布式-Zookeeper-Master选举
|
7月前
|
存储 数据库
zookeeper 集群环境搭建及集群选举及数据同步机制
zookeeper 集群环境搭建及集群选举及数据同步机制
220 2
|
算法 Linux
分布式系列教程(14) -分布式协调工具Zookeeper(集群选举策略)
分布式系列教程(14) -分布式协调工具Zookeeper(集群选举策略)
98 0
|
Java 开发工具 Maven
分布式系列教程(12) -分布式协调工具Zookeeper(选举与哨兵机制)
分布式系列教程(12) -分布式协调工具Zookeeper(选举与哨兵机制)
97 0
|
存储
zookeeper的leader选举原理和底层源码实现超级详解 2
zookeeper的leader选举原理和底层源码实现超级详解
105 1

热门文章

最新文章