zookeeper原理解析-选举

2024-05-07 09:18
文章标签 原理 解析 zookeeper 选举

本文主要是介绍zookeeper原理解析-选举,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

zookeeper原理解析-选举


1)QuorumPeerMain加载

       

Zookeeper集群启动的入口类是QuorumPeerMain来加载配置启动QuorumPeer线程。首先我们来看下QuorumPeer, 谷歌翻译quorum是法定人数,定额的意思, peer是对等的意思,那么QuorumPeer中quorum代表的意思就是每个zookeeper集群启动的时候集群中zookeeper服务数量就已经确定了,在每个zookeeper的配置文件中配置集群中的所有机器

server.1=127.0.0.1:2886:3886 

server.2=127.0.0.1:2887:3887 

server.3=127.0.0.1:2888:3888

事实上着也确定zookeeper在运行中是不能动态扩容的,必须停下服务修改配置才可以;QuorumPeer中peer代表就是集中每个zookeeper角色是对等的没有主从之分,每个zookeeper服务都可以成为leader, follower,observer。

 

1.      QuorumPeerMain加载

1)  QuorumPeerConfig读取配置文件,如下面的zoo.cfg文件

tickTime=2000

initLimit=10

syncLimit=5

dataDir=D:/workspace_zookeeper/data1

clientPort=2181

server.1=127.0.0.1:2886:3886 

server.2=127.0.0.1:2887:3887 

server.3=127.0.0.1:2888:3888

如上配置中每个server.X记录代表集群中的一个服务,QuorumPeerConfig会构建一个QuorumServer对象,其中的server.X中的X代表zookpeer的sid,每个zookeeper都会编辑自己的sid在dataDir目下的myid文件中,sid标记每个服务,在快速选举中起作用

技术分享

 

server.X后值代表zookeeper服务地址ip以及选举其中zookeeper之间连接的端口

2)启动定时清理服务任务DatadirCleanupManager.start() 用来清除过期的txtLog和snapshot文件

3)构建QuorumPeer任务对象

3.1)设置供客户端连接的端口地址

3.2)设置txtLog和snapshot的操作对象FileTxnSnaplog

3.3)设置本Zookeeper的myid(sid)

3.4)设置客户端连接工厂

3.5)设置选举算法

3.6)各种时间设置等等

4)QuorumPeer.start()启动任务线程

2)选举流程

     

uorumPeer的run方法中主要用来进行选举,以及选举后进入各角色,角色被打破重新再进行选举,下图大体流程

技术分享

 

 

2.1.1基本概念

Logicalclock, currentEpoch,acceptedEpoch   epoch  zxid

2.2.2选举算法创建

         Zookeeper启动的时候,quorumPeer线程的start方法的调用startLeaderElection方法来创建选举算法, 创建过程如下:

1) 选举算法的创建之前先创建QuorumCnxManager,QuorumCnxManager利用tcp协议来进行leader选举,每一对server之间都会保持一个tcp链接,每个zookeeper会打开一个tcp/ipj监听集群中的其他server。

         1.1) receiveConnection(socket)方法用来建立连接

                   1.1.1) 读取请求连接zookeeperserver的sid(myid)

                   1.1.2)      对方sid小于自己sid, 立马关闭连接, 自己做为client向对方请求建立连接, 注意zookeeper 服务之间都是配置myid大的作为客户端连接myid小的作为服务器端。

                   1.1.3) 对方sid大于自己sid, 创建server端的发送线程任务和接收线程任务,并且启动任务准备发送和接收client端数据

1.2) connectOne(sid):本zookeeper作为客户端向sid(myid)的zookeeper发起链接请求

        1.2.1) 向对方zookeeper写入本机sid

                   1.2.2) 对方sid大于本机, 关闭socket链接,注意zookeeper服务之间都是配置myid大的作为客户端连接myid小的作为服务器端。

                   1.2.3) 对方sid小于本机,创建client端的发送线程任务和接收线程任务,并且启动任务准备发送和接收server端数据

         1.3) SendWorker: 如同其名字run方法从阻塞的发送队列中取数据发送

         1.4) RecvWorker: 如同其名字run方法将接收到数据放入阻塞队列中,供FastLeaderElection. WorkerReceiver线程任务消费

 

2) QuorumCnxManager.listener.start()

         Listener线程任务, 绑定地址开启ServerSocket服务,用来侦听其他server连接,进行集体间选举,投票, 数据同步。Server链接数有限,是基于bio的长连接。

         Socketclient = serverSocket.accept();

         receiveConnection(client);//处理建立连接请求

 

 

3) FastLeaderElection:创建选举对象

         3.1) 构建发送队列LinkedBlockingQueue<ToSend>sendqueue

         3.2) 构建接收队列LinekdBlockingQueue<Notification>recvqueue

         3.2) 创建消息处理对象Messenger, 它有WorkerReceiver和WorkerSender两个线程子类型对象组成, 这个两个线程对象的作用就如它的名字一样

         3.2.1) WorkerReceiver

         3.2.2) WorkerSender

 

 

2.2.3选举流程:

1) Logicalclock++

2) 初始化提案:

2.1)建议选举的leader自己proposedLeader=myid

2.2)proposedZxid=lastLoggedZxid datatree中记录的最后事务id

2.3)proposedEpoch=currentEpoch 当前本地文件currentEpoch中存储的值

技术分享

 

3)  向其他服务发送通知消息:

     遍历集群中的所有的server, 构建选举建议提案

           ToSend notmsg = newToSend(ToSend.mType.notification,

                    proposedLeader,

                    proposedZxid,

                    logicalclock,

                   QuorumPeer.ServerState.LOOKING,

                    sid,

                    proposedEpoch);

    将消息加入到发送队列中。

4)  LOOKING状态循环:

4.1)从接受队列中获取消息n

4.2) n为空

4.2.1) 发送队列为空,遍历集群中的所有的server, 构建选举建议提案加入发送队列

4.2.1)发送队列不为空, connectAll  查看所有服务如果没有建立连接建立。

         4.3) n不为空, 判断服务状态

                   4.3.1) LOOKING: 接收的投票还没有选举出leader

4.3.1.1)若n.electionEpoch>logicalclock

接受到消息的选举时代大于本机计算器,更新本地logicalclock,

清空收到的投票集合,

然后将收到的消息n跟自己比较判断采用哪种提案,判断规则如下:相等的情况看下一条

newEpoch > curEpoch 

                                      newZxid > curZxid

                                      newId > curId

                            更新选举提案

                            向其他server发送选举提案消息,先加入发送队列异步发送

                   4.3.1.2) n.electionEpoch< logicalclock  对方选举时代过期,废弃,break重新循环

                   4.3.1.3) n.electionEpoch==  logicalclock 决策提案规则如下相等情况看下一条

newEpoch > curEpoch 

                                               newZxid> curZxid

                                               newId > curId

如果采用对方提案, 更新本机提案并向其他server发送选举提案消息,先加入发送队列异步发送

4.3.1.4) 将对方提案构建成投票对象vote,保存到接收投票集合, 到这里本机的提案信息应该是最新的了

4.3.1.5) termPredicate(recvset,new Vote(proposedLeader, proposedZxid, logicalLock, proposedEpoch)) 将接收到的提案跟自己的提案比较,大于一般set.size()>集群数/2

                   如果没有大于一半,跳出本次循环

如果大于一半,从接收队列取消息, 如果有消息判断投票提案有没有更新有更新将消息加入接收集合, 如果接收队列中没有新的消息那么根据最新投票设置本机角色

技术分享

 

                    4.3.2) OBSERVING:

                   选举过程,OBSERVING不参与,只打印debug日志

                   4.3.3) FOLLOWING 或者 LEADING

                   接收的投票信息已经有leader选举出了

                   4.3.3.1) n.electionEpoch== logicalclock 接收到消息选出了leader跟本机是在一个选举时代

                                     将消息加入接收的投票集合recvset

                                     判断recvset集合中是不是多数投个n消息指定的leader

                                     将消息加入一个外部选举的集合outofelection用来存放外部选举出leader的消息

                                     判断大多数outofelection集合中的follower是否跟随同一个leader 

2.2  OBSERVING 本机是观察者

2.2.1)建立跟leader server的socket链接

2.2.2) 向leader server注册本oberser服务, 注册过程除了向leader表明本server的角色外, 还会将自己的acceptedEpoch提交给leader, leader判断更新再向自己反馈最新的acceptedEpoch

2.2.3)从leader同步数据

2.2.4)启动while循环,接收leader指令

           PING: 接收心跳消息, 并将自己持有的session作为心跳内容返回

           PROPOSAL,COMMIT,UPTODATE: 记录日志,不做操作

           SYNC:观察者同步数据

REVALIDATE:  重新建立session

INFORM: 观察者通过这种消息类型来提交数据, (对于follower要先PROPOSAL在COMMIT)

 

2.3  FOLLOWING 本机处于跟随者状态

2.3.1)建立跟leader server的socket链接

2.3.2)向leaderserver注册本follower服务,注册过程除了向leader表明本server的角色外,还会将自己的acceptedEpoch提交给leader, leader判断更新再向自己反馈最新的acceptedEpoch

2.3.3) 做一次检查leader返回的epoch小于本机accpetedEpoch绝不应该出现的

2.3.4)从leader同步数据

2.3.5)启动while循环,接收leader指令

          PING:接收心跳消息, 并将自己持有的session作为心跳内容返回

              PROPOSAL:leader向follower提交了一个变动操作提案

              COMMIT:   leader向follower确认变动操作

              UPTODATE:  follower启动后不应该接受到这个操作

              REVALIDATE:  重新建立session

              SYNC: 同步数据

 

2.4  LEADING 本机处于领导状态

一但选举出leader如果本机就是leader,那么Quorumpeer.run进入LEADING分支进行作为leader角色的初始化及进入leader角色的工作,由Leader.lead()执行,下面我们来看看执行流程:

         2.4.1) loadData加载数据, zookeeperServer利用snapshot和txtLog恢复数据加载到内存

         2.4.2) 获取leader的epoch,lastProcessedZxid

         2.4.3) 构建LearnerCnxAcceptor线程任务并启动

LearnerCnxAcceptor用来侦听集群中的learner(follower&observer),并跟它们建立连接,leader跟每个learner的连接都会构建LearnerHandler线程任务来跟learner一对一单独交流

         2.4.4) 获取最新接收的选举时代epoch

这个是通过接收所有(这里也不是所有,是通过策略,默认大于一般, 否则阻塞等待)zookeeper集群的lastAcceptedEpoch比较出最大一个在加一得出,

2.4.5)根据最新epoch创建新的zxid,高32位是epoch,低32位是id计数

2.4.6)  构建leader, epoch信息的对象QuorumPacket,向集群中的learner发送, learner接收后epoch大于自己acceptedEpoch的更新learner的acceptedEpoch

                   将自己加入newLeaderProposal.ackSet集合

然后接收各个learner反馈(默认大于一半否则会阻塞等待)

                   设置currentEpoch,序列化到本地文件

2.4.7) leader通过learnerhandler与各个learner进行交互,在leader向各个learner发送newLeaderProposal后,各个learner反馈后, 各个learner就会根据最新的epoch,zxid来跟leader进行数据同步,同步完成后会向leader发送ack消息,leader接收到后将ack消息加入到newLeaderProposal.ackSet, 所以leader的下一步操作就是循环判断newLeaderProposal.ackSet个数是否超过一半

2.4.8) 启动while循环用来定时向learner发送心跳, 同时决策集群中活着的server是否大于一半, 如果不是退出循环会重新在选举

3)数据同步

 

1.      Zookeeper集群一旦选举leader后,  leader跟follower,observer之间会进行一些列的交互产生epoch,数据同步操作, 以及后续操作的投票处理决策等操作,这些交互过程其实挺复杂的,zookeeper的代码个人觉的没有整理的很清晰导致深入细节的时候看起来很费劲,下面我就对他们之间的交互做整体并尽可能细致的介绍

3.1)如下图leader.lead()方法创建并启动LearnerCnxAcceptor线程用来侦听follower.followLeader()或者observer.observerLeader()中通过connectToLeader(addr)来连接leader, 每个连接会构建一个LearnerHandler线程对象来专门负责处理。

 

技术分享

 

 

由于follower与observer的差别在于observer不参与选举投票其他都类似,所以下面我就以leader跟follower的交互进行讲解。

 

3.2)leader通过投票获取个sever的lastAccpetEpoch决策出最新的

3.2.1)leader构建LearnerCnxAcceptor,侦听learner链接

3.2.2)learner连接上leader,leader为对于learner构建LearnerHandler处理器

3.2.3)leader将自己sid加入connectingFollowers集合等待决策

            超过半数notifyall

            没有超过半数wait

3.2.4)learner向leader发送自己的lastAccpetEpoch, 如果learner的lastAccpetEpoch大于leader的则更新leader的为learner的lastAccpetEpoch+1, 将learner的sid加入connectingFollowers集合等待决策

           超过半数notifyall

             没有超过半数wait

注: 3.2.3和3.2.4多线程没有先后, 3.2.4会有很多

3.2.5)hold住,等待connectingFollowers超过半数,得到最新的epoch

3.2.6)向learner写入leaderinfo即,leader得到的做下epoch

3.2.7)learner读取leader信息, 更新自己的lastAccpetEpoch

             并向leader反馈更新信息

3.2.8)leader获取learner的反馈, 决策超过半数,返回最新的epoch

技术分享

 

上图是获取epoch的一个立体交互

 

3.3) 数据同步

leader决策出epoch后,zookeeper进入一个新的时代,zookeeper在对外接客之前需要跟leader进行数据同步,数据同步并不是独立组件,代码是紧接着上面获取epoch的。

3.3.1)

 

toBeApplied  commitLog outstandingProposals集合的关系区别

技术分享

 

zookeeper原理解析-选举

标签:nbsp   端口   ast   连接   先后   动态   cvs   space   ntp  

这篇关于zookeeper原理解析-选举的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/966944

相关文章

网页解析 lxml 库--实战

lxml库使用流程 lxml 是 Python 的第三方解析库,完全使用 Python 语言编写,它对 XPath表达式提供了良好的支 持,因此能够了高效地解析 HTML/XML 文档。本节讲解如何通过 lxml 库解析 HTML 文档。 pip install lxml lxm| 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档,下面来介绍一下 lxml 库

Zookeeper安装和配置说明

一、Zookeeper的搭建方式 Zookeeper安装方式有三种,单机模式和集群模式以及伪集群模式。 ■ 单机模式:Zookeeper只运行在一台服务器上,适合测试环境; ■ 伪集群模式:就是在一台物理机上运行多个Zookeeper 实例; ■ 集群模式:Zookeeper运行于一个集群上,适合生产环境,这个计算机集群被称为一个“集合体”(ensemble) Zookeeper通过复制来实现

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

hdu4407(容斥原理)

题意:给一串数字1,2,......n,两个操作:1、修改第k个数字,2、查询区间[l,r]中与n互质的数之和。 解题思路:咱一看,像线段树,但是如果用线段树做,那么每个区间一定要记录所有的素因子,这样会超内存。然后我就做不来了。后来看了题解,原来是用容斥原理来做的。还记得这道题目吗?求区间[1,r]中与p互质的数的个数,如果不会的话就先去做那题吧。现在这题是求区间[l,r]中与n互质的数的和

搭建Kafka+zookeeper集群调度

前言 硬件环境 172.18.0.5        kafkazk1        Kafka+zookeeper                Kafka Broker集群 172.18.0.6        kafkazk2        Kafka+zookeeper                Kafka Broker集群 172.18.0.7        kafkazk3

hdu4407容斥原理

题意: 有一个元素为 1~n 的数列{An},有2种操作(1000次): 1、求某段区间 [a,b] 中与 p 互质的数的和。 2、将数列中某个位置元素的值改变。 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.Inpu

hdu4059容斥原理

求1-n中与n互质的数的4次方之和 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWrit

OWASP十大安全漏洞解析

OWASP(开放式Web应用程序安全项目)发布的“十大安全漏洞”列表是Web应用程序安全领域的权威指南,它总结了Web应用程序中最常见、最危险的安全隐患。以下是对OWASP十大安全漏洞的详细解析: 1. 注入漏洞(Injection) 描述:攻击者通过在应用程序的输入数据中插入恶意代码,从而控制应用程序的行为。常见的注入类型包括SQL注入、OS命令注入、LDAP注入等。 影响:可能导致数据泄

从状态管理到性能优化:全面解析 Android Compose

文章目录 引言一、Android Compose基本概念1.1 什么是Android Compose?1.2 Compose的优势1.3 如何在项目中使用Compose 二、Compose中的状态管理2.1 状态管理的重要性2.2 Compose中的状态和数据流2.3 使用State和MutableState处理状态2.4 通过ViewModel进行状态管理 三、Compose中的列表和滚动