Zookeeper学习6_Zookeeper Server leader选举中的paxos算法实现

本文详细解析了Zookeeper集群中Leader选举的过程,包括Server如何标识、成为Leader的条件及选举算法实现等关键技术细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基本概念

一个Server如何知道其他Server?

在 zookeeper 中,一个 zookeeper 集群有多少个 Server 是固定,每个 Server 用于选举的 IP和 PORT 都在配置文件中;


除IP和Port能标识一个Server之外,还有没有别的方法?

每一个 Server 都有一个数字编号,而且是唯一的,我们根据配置文件中的配置来对每一个Server 进行编号,这一步在部署时需要人工去做,需要在存储数据文件的目录中创建一个文件叫 myid 的文件,并写入自己的编号,这个编号在处理我提交的 value 相同很有用;


成为Leader的必要条件?

获得 n/2 + 1个 Server 同意(这里意思是 n/2 + 1个 Server 要同意拥有 zxid 是所有 Server 最大的哪个 Server);


zookeeper选举中,采用UDP还是TCP?

zookeeper 中选举主要是采用 UDP,也一种实现是采用 TCP,在这里介绍的两种实现采用的是 UDP;


zookeeper有哪几种状态?

LOOKING 初始化状态 

LEADING  领导者状态

FOLLOWING  跟随者状态


如果所有 zxid 都相同(例如: 刚初始化时),此时有可能不能形成 n/2+1个 Server,怎么办?

zookeeper 中每一个 Server 都有一个 ID,这个 ID 是不重复的,而且按大小排序,如果遇到这样的情况时,zookeeper 就推荐 ID 最大的哪个 Server 作为 Leader。


zookeeper 中 Leader 怎么知道 Fllower 还存活,Fllower 怎么知道 Leader 还存活Leader 定时向 Fllower 发 ping 消息,Fllower 定时向 Leader 发 ping 消息,当发现 Leader无法 ping 通时,就改变自己的状态(LOOKING),发起新的一轮选举。


名词解释

zookeeer Server: zookeeper 中一个 Server,以下简称 Server;

 

zxid(zookeeper transtion id): zookeeper 事务 id,他是选举过程中能否成为 leader 的关键因素,它决定当前 Server 要将自己这一票投给谁(也就是我在选举过程中的 value,这只是其中一个,还有 id);

 

myid/id(zookeeper server id): zookeeper server id ,他也是能否成为 leader 的一个因素;


epoch/logicalclock:他主要用于描述 leader 是否已经改变,每一个 Server 中启动都会有一个

epoch,初始值为0,当开始新的一次选举时 epoch 加1,选举完成时 epoch 加1;

 

tag/sequencer:消息编号;

 

xid:随机生成的一个数字,跟 epoch 功能相同;


Fast Paxos 消息流向图与 Basic Paxos 的对比

消息流向图

basic paxos 消息流向图

Client  Proposer  Acceptor  Learner

| | | | |

X--------------->| | Request

| X--------->|->|->| | | Prepare(N)//向所有 Server 提议

| |<---------X--X--X | | Promise(N,{Va,Vb,Vc})//向提议人回复是否


接受提议(如果不接受回到上一步)

| X----------->|->|->| | | Accept!(N,Vn)//向所有人发送接受提议消息

| |<----------X--X--X---——--->|->| Accepted(N,Vn)//向提议人回复自己已经接受提议)

|<--------------------------------------------------X--X  Response

| | | | |


fast paxos 消息流向图

没有冲突的选举过程

Client Leader Acceptor Learner

| | | | | |

| X--------->|->|->|->| Any(N,I,Recovery)

| | | | | |

X-------------------------------->|->|->|->| Accept!(N,I,W)//向所有 Server 提议,

所有 Server 收到消息后,接受提议

| |<---------X--X--X--X------>|->|    Accepted(N,I,W)//向提议人发送接受提

议的消息

|<---------------------------------------------------X--X Response(W)

| | | | | |


第一种实现: LeaderElection

LeaderElection 是 Fast paxos 最简单的一种实现,每个 Server 启动以后都询问其它的 Server它要投票给谁,收到所有 Server 回复以后,就计算出 zxid 最大的哪个 Server,并将这个 Server相关信息设置成下一次要投票的 Server;


 每个 Server 都有一个 response 线程和选举线程,我们先看一下每个线程是做一些什么事情。

 

response 线程

它主要功能是被动的接受对方法的请求,并根据当前自己的状态作出相应的回复,每次回复都有自己的 Id,以及 xid,我们根据他的状态来看一看他都回复了哪些内容;

 

LOOKING 状态:

自己要推荐的 Server 相关信息(id,zxid)

LEADING 状态:

myid,上一次推荐的 Server 的 id

FLLOWING 状态:

当前 Leader 的 id,以及上一次处理的事务 ID(zxid)

 

选举线程

选举线程由当前 Server 发起选举的线程担任,他主要的功能对投票结果进行统计,并选出推荐的 Server。选举线程首先向所有 Server 发起一次询问(包括自己),被询问方,根据自己当前的状态作相应的回复,选举线程收到回复后,验证是否是自己发起的询问(验证 xid 是否一致),然后获取对方的 id(myid),并存储到当前询问对象列表中,最后获取对方提议 的leader 相关信息(id,zxid),并将这些 信息存储到当次选举的投票记录表中,当向所有 Server都询问完以后,对统计结果进行筛选并进行统计,计算出当次询问后获胜的是哪一个Server,并将当前 zxid 最大的 Server 设置为当前 Server 要推荐的 Server(有可能是自己,也有可以是其它的 Server,根据投票 结果而定,但是每一个 Server 在第一次投票时都会投自己),如果此时获胜的 Server 获得 n/2 + 1的 Server 票数, 设置当前推荐的 leader 为获胜的 Server,将根据获胜的 Server 相关信息设置自己的状态。每一个 Server 都重复以上流程,直到选出 leader。

 

了解每个线程的功能以后,我们来看一看选举过程:


·选举过程中,Server 的加入

当一个 Server 启动时它都会发起一次选举,此时由选举线程发起相关流程,那么每个 Server都会获得当前 zxid 最大的哪个 Server 是谁,如果当次最大的 Server 没有获得 n/2+1个票数,那么下一次投票时,他将向 zxid 最大的 Server 投票,重复以上流程,最后一定能选举出一个 Leader。


·选举过程中,Server 的退出

只要保证 n/2+1个 Server 存活就没有任何问题,如果少于 n/2+1个 Server 存活就没办法选出 Leader。


·选举过程中,Leader 死亡

当选举出 Leader 以后,此时每个 Server 应该是什么状态(FLLOWING)都已经确定,此时由于 Leader 已经死亡我们就不管它,其它的 Fllower 按正常的流程继续下去,当完成这个流程以后,所有的 Fllower 都会向 Leader 发送 Ping 消息,如果无法 ping 通,就改变自己的状态为(FLLOWING ==> LOOKING),发起新的一轮选举。


·选举完成以后,Leader 死亡

这个过程的处理跟选举过程中 Leader 死亡处理方式一样,这里就不再描述。


第二种实现: FastLeaderElection

fastLeaderElection 是标准的 fast paxos 的实现,它首先向所有 Server 提议自己要成 为leader,当其它 Server 收到提议以后,解决 epoch 和 zxid 的冲突,并接受对方的提议,然后向对方发送接受提议完成的消息

 

数据结构

本地消息结构:

static public class Notification {

long leader; //所推荐的 Server id

long zxid; //所推荐的 Server 的 zxid(zookeeper transtion id)

long epoch; //描述 leader 是否变化(每一个 Server 启动时都有一个 logicalclock,初始值

为0)

QuorumPeer.ServerState state; //发送者当前的状态

InetSocketAddress addr; //发送者的 ip 地址

}

 

网络消息结构:

static public class ToSend {

int type; //消息类型

long leader; //Server id

long zxid; //Server 的 zxid

long epoch; //Server 的 epoch

QuorumPeer.ServerState state;  //Server 的 state

long tag; //消息编号

InetSocketAddress addr;

}

 

Server 具体的实现

每个 Server 都一个接收线程池(3个线程)和一个发送线程池 (3个线程),在没有发起选举时,这两个线程池处于阻塞状态,直到有消息到来时才解除阻塞并处理消息,同时每个 Server都有一个选举线程(可以发起 选举的线程担任);我们先看一下每个线程所做的事情,如下:

 

被动接收消息端(接收线程池)的处理:

notification:首先检测当前 Server 上所被推荐的 zxid,epoch 是否合法(currentServer.epoch<= currentMsg.epoch && (currentMsg.zxid > currentServer.zxid || (currentMsg.zxid ==currentServer.zxid && currentMsg.id > currentServer.id))) 如 果 不 合 法 就 用 消 息 中 的zxid,epoch,id 更新当前 Server 所被推荐的值,此时将收到的消息转换成 Notification 消息放入接收队列中,将向对方发送 ack 消息

ack:

将消息编号放入 ack 队列中,检测对方的状态是否是 LOOKING 状态,如果不是说明此时已经有 Leader 已经被选出来,将接收到的消息转成 Notification 消息放入接收对队列


主动发送消息端(发送线程池)的处理:

notification: 将要发送的消息由 Notification 消息转换成 ToSend 消息,然后发送对方,并等待对方的回复,如果在等待结束没有收到对方法回复,重做三次 ,如果重做次还是没有收到对方的回复时检测当前的选举(epoch)是否已经改变,如果没有改变,将消息再次放入发送队列中,一直重复直到有 Leader 选出或者收到对方回复为止

 

ack: 主要将自己相关信息发送给对方

 

主动发起选举端(选举线程)的处理:

首先自己的 epoch 加1,然后生成 notification 消息,并将消息放入发送队列中,系统中配置有几个 Server 就生成几条消息,保证每个 Server 都能收到此消息,如果当前 Server 的状态是 LOOKING 就一直循环检查接收队列是否有消息,如果有消息,根据消息中对方的状态进行相应的处理。

 

LOOKING 状态:

首先检测消息中 epoch 是否合法,是否比当前 Server 的大,如果比较当前 Server 的 epoch大时,更新 epoch,检测是消息中的 zxid,id 是否比当前推荐的 Server 大,如果是更新相关值,并新生成 notification 消息放入发关队列,清空投票统计表; 如果消息小的 epoch 则什么也不做; 如果相同检测消息中 zxid,id 是否合法,如果消息中的 zxid,id 大,那么更新当前 Server 相关信息,并新生成 notification 消息放入发送队列,将收到的消息的 IP 和投票结果放入统计表中,并计算统计结果,根据结果设置自己相应的状态

 

LEADING 状态:

将收到的消息的 IP 和投票结果放入统计表中(这里的统计表是独立的),并计算统计结果,根据结果设置自己相应的状态

 

FOLLOWING 状态:

将收到的消息的 IP 和投票结果放入统计表中(这里的统计表是独立的),并计算统计结果,根据结果设置自己相应的状态

 

了解每个线程的功能以后,我们来看一看选举过程,选举过程跟第一程一样


·选举过程中,Server 的加入

当一个 Server 启动时它都会发起一次选举,此时由选举线程发起相关流程,通过将自己的zxid 和 epoch 告诉其它 Server,最后每个 Server 都会得 zxid 值最大的哪个 Server 的相关信息,并且在下一次投票时就投 zxid 值最大的哪个 Server,重复以上流程,最后一定能选举出一个 Leader


·选举过程中,Server 的退出

只要保证 n/2+1个 Server 存活就没有任何问题,如果少于 n/2+1个 Server 存活就没办法选出 Leader


·选举过程中,Leader 死亡

当选举出 Leader 以后,此时每个 Server 应该是什么状态 (FLLOWING)都已经确定,此时由于 Leader 已经死亡我们就不管它,其它的 Fllower 按正常的流程继续下去,当完成这个流程以后,所有的 Fllower 都会向 Leader 发送 Ping 消息,如果无法 ping 通,就改变自己的状态为(FLLOWING ==> LOOKING),发起新的一轮选举


·选举完成以后,Leader 死亡

这个过程的处理跟选举过 程中 Leader 死亡处理方式一样,这里就不再描述


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值