分布式基础-选谁当老大(二)

2020-09-25  本文已影响0人  明翼

前言

上次讨论到谁当老大的问题,介绍了Bully选主算法,比较简单,直接选ID最大或最小的作为leader。这样粗暴的选举算法,没有考虑到数据的新旧,所以可能更容易造成数据丢失的问题。

单纯的论资排辈不一定是最合适的,老人可能没新人能力强,所以又发明了其他的分布式选举算法。本次介绍的是ZAB算法,就是更民主的,选举更新的数据的节点作为leader。ZAB算法全称:Zookeeper Atomic Broadcast ,用一句话解释ZAB协议是保障操作顺序性的,基于主备模式的原子广播协议。

Zookeeper 作为分布式应用服务器,由于高性能和稳定性,和可靠性得到了广泛的应用。
它由Leader,Follower和Observer三种身份成员组成。

# 可以查看zkserver的服务器的身份
./zkServer.sh status
Zookeeper类似文件系统存储结构

一 如何选举

ZAB 支持三种成员身份,有四种状态,三种状态分别代表三种身份。

选举采用投票形式,被选为Leader的不同节点进行相互PK,获取大多数节点投票的Leader会当选。
投票的信息为<Leader, Epoch, LastZxid,node>

Leader :表示为投选择哪个节点作为leader;Epoch:第多少届选举(有的叫任期,我觉得多少届更好),递增的,有这个是为了防止消息延迟造成的不同伦消息相互干扰;LastZxid: 表示被选举为Leader的节点的最大事务ID;Node:即投票的节点。

举例说明: < 3, 1,101,B>
这里面表示节点B 提议节点ID:3 在第一届选举中作为Leader,节点ID:3的最大事务ID为101。
节点开始都会投给自己,然后将此投票信息发送给其他节点,节点收到投票信息后,会进行以下PK:

选举过程

PK过程很简单,届大的获胜,比如人家已经在进行第二轮选举了,你进行第一轮选举,老的失效;
如果时同届选举,lastzxid大的获胜,大的说明数据更新;如果数据一样新,那么大的serverid获胜。
当一个节点获得大部分节点的票之后,就可以当选为leader了。

节点ID可以通过在zoo.cfg里面看到或配置的data目录下有个myid文件,里面也是此节点的id。


集群节点配置

我们以最常见的三个节点组成的Zookeeper集群,来阐述zk如何进行选举。


Zookeeper集群

说明: 初始时候节点A是Leader,节点B和节点C是Follower,只所以选用三个节点,是因为ZK在处理选举或同步数据时候,需要大多数确认,所以一般都是奇数个节点,只所以节点用三个,因为一个不可靠;五个这种选举慢,写性能会弱些,一般三个就够了。

1.1 发生故障 进入选举状态

这时候,节点A发生故障,或网络出现问题,节点B和节点C读取消息的时候超时,进入到LOOKING状态,发起领导者选举,如下:


LOOKING状态

1.2 投票

进入选举阶段后,每个节点都会生成投票信息,初始的时候每个节点都投自己一票,假设节点B的最大事务id为100,serverid为2;节点C的最大事务id为101,serverid为3,则投票的信息如下:


投票

投票消息不光发给其他节点,也发给自己节点。如上图,节点B收到节点C发来的投票信息[3,1,101,C]之后,进行pk,发现届都是1,但是C的最大事务ID:101 大于B的最大的事务ID:100,所以C获胜。B节点调整自己的投票信息:[3,1,101,B] 将这个消息发送给自己和C节点。节点C收到消息后进行PK,C获胜所以不用调整投票信息。

1.3 得到投票结果

按照刚才的逻辑,每个节点都有累加的投票信息,节点ID为3即节点C获得了大多数投票。


投票结果

这样节点C就变更状态为LEADING状态,节点B就变更为FOLLOWING状态。zookeeper就是通过这种方式完成了尽量选择数据最新的节点作为Leader节点。


选举成功

二 ZAB算法特点

ZAB算法的性能不错,对系统没有什么特殊的要求。

三 ZAB选举之后

ZAB选举完成之后,并不能立刻处理请求,还要经历集群发现阶段和数据同步阶段后才可以提供读写服务。
简单的聊下。

比如刚才的B节点和C节点需要进入到DISCOVERY状态,具体如下图:


集群发现阶段
  1. Follwer 主动向Leader发送FollwINFO消息,标注上一届的编号为1.
  2. Leader 回复Follwer LEADINFO消息,包含本次新生成的选举届号2,和本届的事务id为0.
  3. Follwer 判断下如果收到Leader的选举届号更大,则是合法的Leader,回复确认消息ACKEPOH。
  4. Leader收到绝大多数的节点返回的ACKEPOH的确认后就可以正式当选Leader,开展领导者的工作了。
    这时ZAB的状态变更为数据同步状态SYNCHRONIZATION。
  1. Leader 通过比较和Follower数据差异大小选择同步方式,将差异数据放入到队列中。
  2. Leader生成New Leader消息也发送到队列中。
  3. Leader将队列中的数据发送给Follower。
  4. Follower 完成数据的同步。
  5. Follower 回复ACK消息给Leader。
  6. 当Leader 收到大部分节点的ACK消息后,发送UPDATE消息给Follower,表示节点同步完成,进入到广播阶段BROADCAST,正式开始处理消息了。

刚才说数据同步的方式有几种,不同情况选择不同的方式。Leader在内存队列中保存了最近500个(默认)事务ID的最大值和最小值。

其他说明下:

  1. zookeeper是实现的最终一致性,写入到zookeeper的消息,如果通过客户端向任意的节点发起读请求,不一定会读到最新的数据,如果需要读到最新的数据,可以先执行sync命令后再读取节点数据。

  2. zookeeper 对于复制到大多数节点的事务不会丢失,但是对于只复制到少数节点的事务,有可能最终被保留,也有可能被截断,要看新选举的Leader是否包含这个事务。

四诗词欣赏

古诗十九首

[汉] [汉无名氏] 

回车驾言迈,

悠悠涉长道。

四顾何茫茫,

东风摇百草。

所遇无故物,

焉得不速老。

盛衰各有时,

立身苦不早。

人生非金石,

岂能长寿考?

奄忽随物化,

荣名以为宝。


上一篇 下一篇

猜你喜欢

热点阅读