Leader 选举
的原理,也就是大名鼎鼎的 Zab 协议的一部分。
Zab 只是一个协议,或者说只是一个概念,ZooKeeper 是这个协议的具体实现,并不是只有选举用到了 Zab 协议,而是其他地方也用到了。
一、什么是 Leader 选举?
在开始设计之前,我们肯定要先搞懂需求,产品一句话:实现一个 Leader 自动选举的功能。那这句话啥意思呢?
我们先简单回顾一下我们之前所学的 ZooKeeper 知识。
首先 ZooKeeper 是支持集群的,而且它有三个角色:Leader、Follower、Observer。我们也知道这三者之间的区别:只有 Leader 能写操作,Follower 和 Observer 只读,且 Follower 可以参与选主,而 Observer 没权利参与选主。这些知识我们前面都讲解过,如下图:
接下来,我们想一个问题:前面说了,只有 Leader 能写操作,那如果 Leader 宕机了,怎么办?这时候整个集群处于亚健康状态,完全不可写了,只能读操作。总不能一直傻傻地等着 Leader 重新起来之后再继续提供写能力吧?所以优秀的产品提了一个需求:当 Leader 宕机后,Follower 要立即开始进行选主,选主的意思就是从 Follower 当中选择一个“最优秀”的出来,让它升级为 Leader
。
现在需求算是彻底搞懂了,但是我们仍然有很多疑问,比如:我选择哪个 Follower 升级为 Leader 呢?选举流程是咋样的呢?宕机的 Leader 重启来后该何去何从呢?等等一系列问题,接下来就开始逐个攻破~
我们先来看第一个问题:选择哪个 Follower 升级为 Leader 呢?
二、选择哪个 Follower 升级为 Leader?
这个问题,我们大家肯定异口同声地说:当然是哪个 Follower 上的数据最新就哪个 Follower 当 Leader!没错,这是必然的,那我问你:如果多台 Follower 上的数据都一样新,这时候该让谁来当 Leader 呢?我们接下来就好好研究一下这个问题。
现在我们知道了一个条件,那就是:哪个 Follower 上的消息最新就让哪个 Follower 优先被升级为 Leader。 那我们就用 zxid 来标记,zxid 的值越大就代表数据越新。那这个 zxid 啥时候更新呢?也很简单,每一次写请求,就更新一次 zxid,让 zxid 自增 1。
接下来就来到了我们的问题:如果 zxid 一样的话,该怎么选择?
我们在搭建集群的时候都会写一个如下的配置:
server.1= ZooKeeper 1:2888:3888
server.2= ZooKeeper 2:2888:3888
server.3= ZooKeeper 3:2888:3888
我们可以发现server后面有个数字:.1 .2 .3
。这是什么呢?这个其实就是一个编号,但是既然要这么写,那就有这么写的意义,这个的意义就在于 Leader 选举会用到。如果 zxid 相同的话,那就代表数据都一样,选谁都行,那索性选择一个 serverId 最大的,也就是选择server.
后面数字最大的那个服务,我们也给它起个名字,叫 myid 吧。
现在我们先简单用一句话总结一下:先对比 zxid,zxid 最大的优先被选举,若 zxid 一致,那么就选择一个 myid 最大的。
有了 zxid 和 myid 就够了吗?其实是不完美的,我的需求想要知道目前一共选举多少次了,且当前这次的 zxid 是多少,比如 Leader 宕机了,其他节点进行了重新选主,选完后我希望 zxid 从 0 开始,就好比古代更朝换代,都更朝换代了,我不可能留着上一波的东西,所以我要初始化 zxid
。那这里也简单了,加一个字段标记朝代次数不就好了?每次重新选主成功后就给朝代次数加 1 且初始化 zxid。
可以的,但是不够优雅,我们可以把这两个字段合二为一,统称为 zxid。我们 zxid 本身设计是一个自增的 long 类型字段,long 类型是 64 位的,我们可以把前 32 位作为朝代次数,后 32 位作为事务日志id(也就是我们前面一直说的 zxid ),然后这前 32 位结合后 32 位统称为 zxid。
标签:zxid,选主,Zookeeper,选举,ZooKeeper,我们,Follower,Leader From: https://www.cnblogs.com/fxh0707/p/17204843.html