编程技术网

关注微信公众号,定时推送前沿、专业、深度的编程技术资料。

 找回密码
 立即注册

QQ登录

只需一步,快速开始

极客时间

Zookeeper 原理及Zookeeper 选举机制和流程

一生何求 分布式系统 2021-12-21 23:52 413人围观

腾讯云服务器

Zookeeper 原理

ZooKeeper 集群的角色

Zookeeper 是一个基于主从复制的高可用集群。通常 3 台服务器就可构成一个 ZooKeeper 集群。ZooKeeper 官方提供的架构图就是一个 ZooKeeper 集群整体对外提供服务。

每一个 Server 代表一个安装 ZooKeeper 服务的服务器,组成 ZooKeeper 服务的服务器都会在内存中维护当前的服务器状态,并且每台服务器之间都互相保持着通信。

Zookeeper 的角色包括 Leader、Follower 和 Observer。

Leader

一个运行中的 Zookeeper 集群只有一个 Leader 服务,Leader 服务主要有 2 个职责:

  • 负责集群数据的写操作
  • 发起并维护各个 Follower 及 Observer 之间的心跳以监听集群的运行状态。

Zookeeper 集群中所有写操作都必须经过 Leader,只有 Leader 写操作完成后,才将写操作广播到其他 Follower。只有超过半数节点(不包括 Observer 节点)写入成功时,该写请求才算写成功。

Follower

一个运行中的 Zookeeper 集群只有一个 Follower,Follower 通过心跳和 Leader 保持连接。Follower 服务主要有 2 个职责:

  • 负责集群数据的读操作
  • 参与集群的 Leader 选举

Follower 在接收到一个客户端请求后会先判断该请求是读请求还是写请求,如果是读请求,那么 Follower 从本地节点上读取数据并返回给客户端;如果是写请求,那么 Follower 会将写请求转发给 Leader 来处理;此外,如果 Leader 失效, Follower 需要在集群选举时进行投票。

Observer

一个运行中的 Zookeeper 集群只有一个 Observer,Observer 的主要职责是负责集群数据的读操作。Observer 与 Follower 的功能类似,但是 Observer 无投票权。

Zookeeper 集群在运行过程中需要支持更多的客户端并发操作,就需要更多的服务实例,而更多的服务实例会使集群投票阶段变得复杂,集群选主时间过程,不利于集群故障快速恢复。因此,Zookeeper 中引入 Observer,Observer 不参与投票,但是接收来自客户端的连接并响应客户端的读请求,将写请求转发给 Leader。加入更多的 Observer节点,不仅提高了 Zookeeper 集群的吞吐量,也保障了系统的稳定性。

ZAB 协议

ZAB(ZooKeeper Atomic Broadcast) 协议即 Zookeeper 原子广播协议。

在 ZooKeeper 中,主要依赖 ZAB 协议来实现分布式数据一致性,基于该协议,ZooKeeper 实现了一种主备模式的系统架构来保持集群中各个副本之间的数据一致性。

Epoch & Zxid

Epoch 即当前集群的周期号(年代号),集群的每次 Leader 变更都会产生一个新的周期号,周期号的产生规则是在上一周期号的基础上加 1,当之前的 Leader 崩溃恢复后会发现自己的周期号比当前的周期号小,说明此时集群已经产生了新的 Leader,旧的 Leader 会再次以 Follower 的角色进入集群。

Zxid 即 ZAB 协议的事务编号,是一个 64 bit 的数据,其中低 32 bit 是一个单调递增的计数器,对于客户端的每一个事务请求,计数器都加 1,高 32 bit 存储 Epoch。每次选举产生一个新的 Leader 时,该 Leader 都会从当前服务器日志中取出最大的 Zxid,获取其中搞 32 bit 的 Epoch 值并加 1,作为新的 Epoch,并将低 32 bit 从 0 开始计数。Zxid 用于标识一次提议的 id,为了保证顺序性,Zxid 必须单调递增。

ZAB 协议的 2 种模式

ZAB 协议有 2 种模式:恢复模式和广播模式。

  • 恢复模式(集群选主)

    在集群启动、集群重启或者 Leader 奔溃后,集群将开始选主,该过程即为恢复模式。

  • 广播模式(数据同步)

    当 Leader 被选举出来后,Leader 将最新的集群状态广播给其他 Follower,该过程即为广播模式。在半数以上是我 Follower 完成与 Leader 状态同步后,广播模式结束。这里的状态同步是指数据同步,用来保证集群中存在过半的机器能够和 Leader 的数据状态保持一致。

ZAB 协议的 4 个阶段

1. 选举阶段 (Leader Election)

在集群选举开始时,所有节点都处于选举阶段。当某一个节点的票数查过半数节点后,该节点将被当选为准 Leader 。

只有到达广播阶段后,准 Leader 才会成为真正的 Leader。

选举阶段的目的是产生一个准 Leader。

2. 发现阶段 (Discovery)

在发现阶段,Followers 开始和准 Leader 进行通信,同步 Followers 最近接收的事务提议。此时,准 Leader 会产生一个新的 Epoch,并尝试让 Followers 接收该 Epoch 后再更新到本地。

发现阶段的一个 Follower 只会连接一个 Leader,如果节点 1 认为节点 2 是 Leader,那么节点 1 就是就会尝试连接节点 2,若连接被拒绝,则集群会重新进入选举阶段。

发现阶段的主要目的是发现大多数节点接收的最新提议。

3. 同步阶段 (Synchronization)

同步阶段主要是利用 Leader 前一阶段获得的最新提议信息同步到集群中所有副本,只有当半数以上的节点都同步完成后,准 Leader 才会成为真正的 Leader。

同步阶段完成后集群选主操作才完成,新的 Leader 将产生。

4. 广播阶段 (Broadcast)

到了广播阶段,ZooKeeper 集群才能正式对外提供事务服务,并且 Leader 进行消息广播,将其上的状态通知到其他 Follower。如果有新的节点加入,那么 Leader 需要对新节点进行状态同步。

ZAB 协议的 Java

Zookeeper 选举机制和流程

Zookeeper 选举机制

每个 Server 都可提议自己是 Leader,并为自己投票,然后将投票结果与其他 Server 的选票进行对比,权重大的胜出。具体选举过程如下:

  • 每个 Server 启动后都询问其他 Server 给谁投票,其他 Server 根据自己的状态回复自己推荐的 Leader 返回对应的 Leader id 和 Zxid。在集群初次启动时,每个 Server 都会推荐自己为 Leader。
  • 当 Server 收到所有其他 Server 回复后,计算出 Zxid 最大的 Server,并将该 Server 设置成下一次要投票的 Server。
  • 计算过程中票数最多的 Server 将成为获胜者,如果获胜者的票数超过集群个数的一半,则该 Server 就被推选为 Leader。否则继续投票,直到 Leader 被选举出来。
  • Leader 等待其他 Server 连接。
  • Follower 连接 Leader,将最大的 Zxid 发送给 Leader。
  • Leader 根据 Follower 的 Zxid 确定同步点,至此,选举阶段完成。

在选举阶段完成后,Leader 通知其他 Follower,集群已成为 Uptodate 状态,Follower 收到 Uptodate 消息后,接收客户端请求开始对外提供服务。

ZAB 协议的 Java 实现

ZAB 协议的 Java 实现与其定义略有不同,在实际实现时,选举阶段采用 Fast Leader Election 模式。在该模式下,节点首先向所有 Server 提议自己要成为 Leader,当其它 Server 收到提议后,判断 Epoch 信息并接受对方的提议,然后向对方发送接收提议完成的消息;同时,在 Java 的实现过程中将发现阶段和同步阶段合并为恢复阶段(Recovery)。因此,ZAB 协议的 Java 实现只有 3 个阶段:Fast Leader Election、Recovery 和 Broadcast。

具体选举过程

以 5 台 Server 选主为例:

  • S1 启动

    S1 提议自己为 Leader 并为自己投票,然后将投票结果发送给其他 Server,此时其他 Server 还未启动,因此收不到任何反馈信息。S1 就处于 Looking 状态。

  • S2 启动

    S2 提议自己为 Leader 并为自己投票,然后与 S1 交换投票结果,由于 S2 的 Zxid 大于 S1 的 Zxid,S2 胜出,但是投票未过半,S1 和 S2 均处于 Looking 状态。

  • S3 启动

    S3 提议自己为 Leader 并为自己投票,然后与 S1、S2 交换投票结果,由于 S3 的 Zxid 值最大,所以 S3 胜出。此时 S3 的票数过半,S3 就是 Leader,S1 和 S2 成为 Follower。

  • S4 启动

    S4 提议自己为 Leader 并为自己投票,然后与 S1、S2、S3 交换投票结果,发现 S3 已经成为 Leader,S4 就成为 Follower。

  • S5 启动

    S5 提议自己为 Leader 并为自己投票,然后与 S1、S2、S3和 S4 交换投票结果,发现 S3 已经成为 Leader,S5 就成为 Follower。

关于 ZooKeeper 集群的几个问题

  • ZooKeeper 集群中一般部署奇数台 Server,why ?

    这是因为 ZooKeeper 集群在宕掉几个 Server 后,如果剩下的 Server 数大于宕掉的 Server 数的话整个 ZooKeeper 才依然可用。假如我们的集群中有 n 台 Server ,那么也就是剩下的服务数必须大于 n/2。

    假设有 3 台服务器,那么最大允许宕掉 1 台 ZooKeeper 服务器,如果我们有 4 台的的时候也同样只允许宕掉 1 台;假如有 5 台服务器,那么最大允许宕掉 2 台 ZooKeeper 服务器,如果我们有 6 台的的时候也同样只允许宕掉 2 台。可以看出,2n 和 2n-1 的容错度是一样的,所以采用奇数台 Server 就行了。

  • ZooKeeper 为何采用选举过半机制?

    采用过半机制是如何防止集群脑裂。

    集群脑裂指的是对于一个集群,如果发生网络故障,Server 之间不能正常通信,集群被割裂成几个小集群,此时子集群各自进行选主导致“脑裂”的情况。

    假设一个由 6 台服务器所组成的集群,部署在了 2 个机房,每个机房 3 台。正常情况下只有 1 个 Leader,但是当两个机房中间网络断开的时候,每个机房的 3 台服务器都会认为另一个机房的 3 台服务器下线,而选出自己的 Leader 并对外提供服务。若没有过半机制,当网络恢复的时候会发现有 2 个 Leader。这好比原来的 1 个大脑(Leader)分散成了 2 个大脑,这就发生了脑裂现象。脑裂期间 2 个 “大脑” 都可能对外提供了服务,会带来数据一致性等问题。而 ZooKeeper 的过半机制导致不可能产生 2 个 Leader,因为少于等于一半是不可能产生 Leader 的,这就使得不论机房的机器如何分配都不可能发生脑裂。

腾讯云服务器 阿里云服务器

上一篇

关注微信
^