写点什么

ZooKeeper,到底如何选主?

用户头像
奈学教育
关注
发布于: 2020 年 05 月 19 日

奈学教育为我们重点分析 ZooKeeper 的 Leader 选举算法。Leader 的选举是 ZooKeeper 的最重要技术之一,也是保证分布式系统数据一致的关键。

Leader 选举流程概述 

我们本篇文章的目的就是详细的剖析 Leader 选举的过程,但是 Leader 选举的过程较为复杂,我们直接上来就讲其详细的过程,大家容易蒙圈,所以我们这一小段就简单描述一下 Leader 选举的大概流程。

如上图所以,假设我们目前有一个 3 个节点构成的 ZooKeeper 集群,myid 的编号分别是 0,1,2,又因为集群当前是一个空的集群,所以每个节点的 ZXID 初始都为 0,该集群启动的时候 Leader 的选举流程如下:

(1)我们首先启动 myid 为 0 的服务,但是目前只有一台 ZooKeeper 服务,所以是无法完成 Leader 选举的,ZooKeeper 集群要求 Leader 进行投票选举条件是至少有 2 台服务才行,不然都没法进行通信投票。

(2)启动 myid 为 1 的服务,第二台启动了以后,这两台 ZooKeeper 就可以相互通信了,接下来就可以进行投票选举了。

(3)2 台 ZooKeeper 进行投票选举的时候,第一次都是推荐自己为 Leader,投票包含的信息是:服务器本身的 myid 和 ZXID。比如第一台投自己的话,它会发送给第二台机器的投票是(0,0),第一个 0 代表的是机器的 myid,第二个 0 代表是的 ZXID。故两台机器收到的投票情况如下:

第一台:(1,0)

第二台:(0,0)

(4)两台服务器在接收到投票后,将别人的票和自己的投票进行 PK。PK 的是规则是:

(a)优先对比 ZXID,ZXID 大的优先作为 Leader(ZXID 大的表示数据多)

(b)如果 ZXID 一样的话,那么就比较 myid,让 myid 大的作为 Leader 服务器。

那根据这个规则的话,第一台服务器,接受到的投票是(1,0),跟自己的投票(0,0)比,ZXID 是一样的,但是 myid 比接收到的投票的小,所以第一台原先是推荐自己投票为(0,0),现在进行了 PK 以后,投票修改为(1,0)。第二台服务器,接受到的投票是(0,0),跟自己的投票(1,0)比,ZXID 是一样的,但是 myid 是比接受到的投票的大,所以坚持自己的投票(1,0)。两台服务器再次进行投票。

(5)每次投票以后,服务器都会统计所有的投票,只要过半的机器投了相同的机器,那么 Leader 就选举成功了,上面的两台服务器进行第二次投票之后,两台服务器都会收到相同的投票(1,0)。那么此时 myid 为 1 的服务器就是 Leader 了。

如上的 Leader 选举其实在集群启动的过程中只需要几毫秒就完成了,所以如果有搭建 ZooKeeper 集群经验的同学会发现,我们如果按顺序启动服务的话,启动到第二台机器的时候,Leader 就已经选出来了,所以大家会看到一般第二台就是 Leader。第三台启动的时候就作为 Follower。

上面我们描述的是集群在初始化过程中 Leader 的选举流程,如果集群在运行的过程中 Follower 节点宕机了,对 Leader 节点是不影响的,如果集群在运行的过程中 Leader 节点宕机了,就会进行重新选举,重新选举的流程跟上述一致。

Leader 选举的详细流程 

如上图是 ZooKeeper 选举的核心算法逻辑图,接下来我们详细的看一下其选举流程。

0x01 投票轮次递增

用于标识当前投票的轮次,ZooKeeper 规定了同一轮次的投票才是有效的。所以如果要进行新一轮的投票,需要对投票轮次进行递增。

0x02 初始化选票

在投票之前每台服务器都会初始化自己的选票,选票里面最重要的两个值一个是本机的 myid 的值,一个是本机的 ZXID 的值。

0x03 发送初始化选票

完成选票的初始化以后,服务器就会发起第一次投票,第一次投票都是推荐自己为 Leader,也就是都投自己。

0x04 判断服务状态

ZooKeeper 的服务有四个状态:LOOKING, FOLLOWING, LEADING, OBSERVING

LOOKING:寻找 Leader 的状态。

FOLLOWING:跟随者状态。

LEADING:领导者状态。

OBSERVING:观察者状态。

如果当前服务的状态是 LOOKING,那么说明还没选举出来 Leader,继续下面的步骤,正常情况下一开始都是 LOOKING 的状态。

0x05 接受外部选票

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

0x06 判断选举轮次

发送完初始化选票以后,接下来就要处理外部的选票了,处理选票的时候会根据不同轮次的选票进行不同的处理。

6.1 外部投票的选举轮次大于自己的轮次

如果发现自己的投票轮次小于外部的轮次,那么立即更新自己的轮次,然后清空已经接收到的选票。然后使用初始化的选票来 PK 刚刚的外部投票以确定是否变更自己的投票(PK 的规则跟概述里描述一致)。

6.2 外部投票的选举轮次小于自己的轮次

如果接收到的选票的选举轮次落后与服务器本身的轮次,那么直接忽略该外部选票,不做任何处理。

6.3 外部投票的选举轮次等于自己的轮次

大多数属于这个情况,如果外部的选票的轮次跟自己的选票轮次一致的话,就进行选票 PK。

0x07 选票 PK

(a)优先对比 ZXID,ZXID 大的优先作为 Leader。

(b)如果 ZXID 一样的话,那么就比较选票里的 myid,myid 大的选为 Leader。

0x08 变更选票

通过选票 PK 以后,如果确定了别的服务的选票优于自己的选票,那么就进行选票变更,把自己的选票信息变更为更适合作为 Leader 的服务器的选票信息。然后再把这些选票发送出去。不过无论是否发生了选票变更,当前的服务都会将刚刚接收到的选票进行归档并按照服务器的 myid 来区分,如:{(0,vote1),(1,vote2),....}

0x09 统计投票

完成了选票归档之后,就可以统计选票了,说白了就是看是否有过半的服务器认为某台服务器适合做 Leader,如果确定了则终止投票。否者返回步骤(4)。

0x0A 更新服务状态

统计投票后,如果已经确定出来 Leader 就终止投票,接下来就变更服务的状态,首先看一下自己是不是 Leader,如果自己是 Leader 那么就更新自己的状态为 Leader,如果不是 Leader,那么就根据配置文件,要么切换为 Follower,要么切换为 Observer。

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

最后

ZooKeeper 是我们学习架构的过程中必不可少的一个技术,今天主要跟大家讲解了 ZooKeeper 的 Leader 选举算法,后面会陆续剖析 ZooKeeper 的 ZAB 协议算法,数据快照机制,数据清理机制,会话机制,长连接机制等。


发布于: 2020 年 05 月 19 日阅读数: 106
用户头像

奈学教育

关注

还未添加个人签名 2020.05.09 加入

还未添加个人简介

评论

发布
暂无评论
ZooKeeper,到底如何选主?