ZooKeeper 的 Leader 选举

1. 前言

我们在 Zookeeper 集群模式一节中,我们学习了为什么要使用 Zookeeper 的集群模式,是因为我们需要保证 Zookeeper 服务的高性能和高可用性。既然使用 Zookeeper 的集群模式,那么避免不了的问题就是 Zookeeper 如何进行 Leader 的选举以及和如何保证 Zookeeper 服务的数据一致性。那么本节我们就来讲解 Zookeeper 服务是如何进行 Leader 选举的。

2. Zookeeper 的 Leader 选举

Zookeeper 的 Leader 选举发生在两个阶段:

  1. Zookeeper 服务初次启动时的 Leader 选举。
  2. Zookeeper 崩溃恢复时的 Leader 选举。

首先我们来讲解在 Zookeeper 服务启动时的 Leader 选举。

2.1 Zookeeper 服务启动时的 Leader 选举

在 Zookeeper 服务启动阶段,每个 Zookeeper 服务会根据配置文件选择启动模式。

在选择集群模式的情况下,获取配置文件中所有 Zookeeper 服务的地址,然后向其它 Zookeeper 服务发起通信检查,确认 Zookeeper 服务间的通信状态。然后在这些 Zookeeper 服务间寻找 Leader 节点,初次启动时无 Leader 节点,此时就会进入 Leader 选举的状态。

在选举状态中,所有 Zookeeper 服务的状态都会变为 Looking 选举状态,每台 Zookeeper 服务都把自己当作 Leader 候选者向其它 Zookeeper 服务发送自己的选票信息。我们这里以 3 个 Zookeeper 服务为例子:
Zookeeper第一轮选举
选票信息包括 Zookeeper 的服务ID,也就是 myid 文件中的内容,还有就是 Zookeeper 服务最新的事务ID,也就是 ZXID,当然初次启动的 Zookeeper 服务的事务 ID 都是相同的 。发送选票信息的同时,也会接收到其它 Zookeeper 服务发送的选票信息。

Tips: ZXID:节点本地的事务编号,由64位的数字组成,包含纪元值( epoch )和计数两部分。

正常情况下,在第一轮的选举中,每个 Zookeeper 服务的选票信息都是自身的信息,所以不会产生 Leader,此时就会开启第二轮选举。

在第二轮选举之前,Zookeeper 服务会把自己的选票信息和接收到的其它 Zookeeper 服务的选票信息一起做比较,产生新的选票信息,首先比较 ZXID,选取拥有较大的 ZXID 的选票信息作为自己新的选票,如果 ZXID 相同,则会比较服务ID,也就是 myid 的值,选取拥有较大的 myid 值的选票信息作为自己新的选票。
Zookeeper选票更新
产生了新的选票之后,发起第二轮投票,此时 Zookeeper 服务器会统计所有服务器发出的选票,如果超过半数的 Zookeeper 服务的选票信息是相同的,那么该选票中的 myid 值相对应的 Zookeeper 服务就当选为 Leader 服务,其状态变为 Leading,其它 Zookeeper 服务的状态由 Looking 状态变为 Following,也就是 Follower 服务。如果选票的统计未达到半数以上,则更新各个节点的选票信息,重新开始新一轮的选举,直到选举出 Leader。
Zookeeper第二轮选举
以上就是 Zookeeper 服务启动时的 Leader 选举的过程。接下来我们讲解 Zookeeper 在崩溃恢复阶段的 Leader 选举。

2.2 Zookeeper 的 ZAB 协议

2.2.1 什么是 ZAB 协议

Zookeeper 使用 ZAB 协议来保证 Zookeeper 的数据一致性,ZAB 协议全称 Zookeeper Atomic Broadcast ,原子消息广播协议。

ZAB 协议的两种工作模式:

  1. 崩溃恢复
  2. 消息广播

ZAB 协议定义了三种节点状态:

  1. Looking:选举状态;
  2. Following:从节点所处的状态;
  3. Leading:主节点所处的状态。

那么 ZAB 协议的这两种模式什么时候使用呢?三种节点的状态又是如何变化的呢?

接下来,我们来详细了解一下 ZAB 的崩溃恢复模式是如何工作的。

2.2.2 ZAB 的崩溃恢复模式

在 Zookeeper 集群服务的运行过程中,如果 Leader 节点发生故障,无法处理 Follower 节点提交的事务请求,根据 ZAB 协议,此时的 Zookeeper 集群就会暂时停止对外提供服务,进入崩溃恢复。如果此时崩溃的 Leader 服务故障被排除,加入到 Zookeeper 集群中,它也会进入 Looking 状态,参与选举。

Zookeeper 的崩溃恢复分为 3 个阶段:

  1. Leader election
    在 Leader 选举阶段,Zookeeper 服务都为 Looking 状态,每个 Zookeeper 服务都会用自身的 ZXID 和 myid 值形成选票,第一轮选举和 Zookeeper 启动时第一轮选举的结果一样,Zookeeper 服务的选票信息都是自身的信息,所以不会产生 Leader,无 Leader 产生 Zookeeper 服务就会更新自身的选票信息,进入下一轮选举,直到选举出 Leader。

    这一阶段选举出来的 Leader 还不能直接作为真正的 Leader 去处理事务请求,它还需要再次确认自身的数据是最新的,避免网络等原因出现多个 Leader 的情况,接下来就进入 Discovery 发现阶段。

  2. Discovery
    在 Discovery 发现阶段,上一阶段产生的 Follower 服务会把自身 ZXID 中的 epoch 纪元值发送给 Leader 服务,Leader 接收到所有 Follower 的 epoch 纪元值后,会选出其中最大的 epoch 纪元值,然后在这基础上进行加 1 ,作为最新的 epoch 纪元值,返回给所有的 Follower 。

    Follower 接收到 Leader 发送的最新 epoch 纪元值后,根据此 epoch 纪元值来更新自己的 ZXID ,然后再把更新后的 ZXID 、最新的历史事务日志和 ACK 确认信息返回到 Leader。

    Leader 接收到 ACK 确认信息后,把接收到最新的 ZXID 和 最新的历史事务日志和自身作比较,把最新的更新到自身。

    经过这一阶段就能确认 Leader 服务的数据是最新的了,然后就进入下一阶段,Synchronization 同步阶段。

  3. Synchronization
    Synchronization 同步阶段的主要作用是把 Leader 最新的数据和日志同步到 Follower 中,当半数以上的 Follower 同步数据成功后,Leader 才能成为真正的 Leader ,就可以处理事务请求了。

经过崩溃恢复的 3 个阶段,真正的 Leader 选举完成后,Zookeeper 就会进入消息广播模式,重新对外提供服务。

3. 总结

经过本节的学习,我们知道了 Zookeeper 在启动时和崩溃恢复时的 Leader 选举时如何完成的,也了解了 Zookeeper 崩溃恢复的 3 个阶段。以下是本节内容的总结:

  1. Zookeeper 在启动时的 Leader 选举。
  2. Zookeeper 的 ZAB 协议。
  3. ZAB 协议的崩溃恢复过程。
  4. Zookeeper 崩溃恢复的 3 个阶段。