ZooKeeper 入门教程之一

大纲

前言

学习资源

ZooKeeper 介绍

ZooKeeper 的概述

Zookeeper 是一个开源的分布式的、为分布式框架提供协调服务的 Apache 项目。

ZooKeeper 的特点

  • (1) Zookeeper 集群:由一个领导者(Leader),多个跟随者(Follower)组成的集群。
  • (2) 集群中只要有半数以上节点存活,Zookeeper 集群就能正常服务,所以 Zookeeper 适合部署奇数台服务器。
  • (3) 全局数据一致:每个 Server 保存一份相同的数据副本,Client 无论连接到哪个 Server,数据都是一致的。
  • (4) 更新请求按顺序执行,来自同一个 Client 的更新请求按其发送顺序依次执行。
  • (5) 数据更新原子性,一次数据更新要么成功,要么失败。
  • (6) 实时性,在一定时间范围内,Client 能读到最新数据。
  • (7) 可以保证 CAP 理论中的 CP(一致性与分区容错性)。

ZooKeeper 的工作机制

Zookeeper 从设计模式角度来理解:是一个基于观察者模式设计的分布式服务管理框架,它负责存储和管理观察者都关心的数据,然后接受观察者的注册;一旦这些数据的状态发生变化,Zookeeper 就负责通知已经在 Zookeeper 上注册的那些观察者做出相应的反应。

ZooKeeper 的数据结构

ZooKeeper 数据模型的结构与 Unix 文件系统很类似,整体上可以看作是一棵树,每个节点称做一个 ZNode。每一个 ZNode 默认能够存储 1MB 的数据,每个 ZNode 都可以通过其路径进行唯一标识。

ZooKeeper 的应用场景

  • ZooKeeper 的适用场景

    • 统一命名服务
    • 统一配置管理
    • 统一集群管理
    • 软负载均衡
    • 服务器节点动态上下线
  • ZooKeeper 的不适用场景

    • 高吞吐量需求:ZooKeeper 在高吞吐量的场景下可能会成为性能瓶颈,性能受限于单点和写操作。
    • 低延迟要求:由于需要保证一致性,ZooKeeper 可能会导致较高的延迟,不适合对延迟要求严格的系统。
    • 大规模数据存储:ZooKeeper 更适用于小数据量的存储,存储大规模数据时效率较低。
    • 分布式计算:ZooKeeper 不适合进行复杂的分布式计算任务,更多是协调和管理服务。
    • 无强一致性要求的场景:对于不需要强一致性的应用,ZooKeeper 的强一致性保证可能是过度设计。
    • 频繁节点变化:在节点频繁变化的场景下,ZooKeeper 的性能可能会受到影响,尤其在极高频率的情况下。
    • Leader 单点故障问题:虽然 ZooKeeper 支持主备机制,但其客户端仍依赖一个活跃的 ZooKeeper 节点(Leader),如果集群不可用(比如集群正在选举新的 Leader),系统可能会受到影响。
    • 非常高的并发写操作:由于 ZooKeeper 是以强一致性为基础的,因此在高并发写操作的场景下可能不适合。

Leader 节点的单点故障问题

ZooKeeper 集群采用了 ZAB 协议,保证了数据的一致性。在集群中,只有一个 Leader 节点 负责处理所有写请求,其他节点作为 Follower 节点提供读取服务。当 Leader 节点发生故障时,集群会进行选举,选出新的 Leader 节点。这个过程需要一定的时间(通常是几秒到几十秒),在此期间,ZooKeeper 服务可能会不可用或者处于一致性恢复阶段。 因此,虽然 ZooKeeper 是集群化部署的,但在 Leader 节点故障期间,集群仍然可能出现短暂的不可用或一致性恢复的现象,这就相当于一种单点故障。不过,这个故障通常是暂时的,因为选举和恢复机制能够尽快解决问题。

统一命名服务

在分布式环境下,经常需要对应用 / 服务进行统一命名,以便于识别。例如:IP 不容易记住,而域名容易记住。

统一配置管理

  • 分布式环境下,配置文件同步非常常见

    • (1) 一般要求在一个集群中,所有节点的配置信息是一致的,比如 Kafka 集群。
    • (2) 对配置文件进行修改后,希望能够快速同步到各个节点上。
  • 配置管理可交由 ZooKeeper 实现

    • (1) 可将配置信息写入 ZooKeeper 上的一个 Znode。
    • (2) 各个客户端都监听这个 Znode 的数据变化。
    • (3) 一旦 Znode 中的数据被修改,ZooKeeper 将通知各个客户端。

统一集群管理

  • 分布式环境中,实时掌握每个节点的状态是必要的

    • (1) 可以根据节点实时状态做出相应的处理。
  • ZooKeeper 可以实现实时监控节点的状态变化

    • (1) 可以将节点信息写入 ZooKeeper 上的一个 ZNode。
    • (2) 监听这个 ZNode 就可以获取它的实时状态变化。

软负载均衡服务

在 Zookeeper 中记录每台服务器的访问数,让访问数最少的服务器去处理最新的客户端请求。

服务器动态上下线

  • 分布式环境中,客户端能实时感知到服务器上下线的变化。

ZooKeeper 单机安装

ZooKeeper 集群安装

ZooKeeper 集群选举

ZooKeeper 集群的选举机制是高频面试题,其中分为第一次启动和非第一次启动两种情况。

集群第一次启动

  • (1) 服务器 1 启动,发起一次选举。服务器 1 投自己一票,此时服务器 1 的票数是一票,不够半数以上(一共有 5 票),选举无法完成,服务器 1 的状态保持为 LOOKING。

  • (2) 服务器 2 启动,再发起一次选举。服务器 1 和 2 分别投自己一票并交换选票信息,此时服务器 1 发现服务器 2 的 myid 比自己目前投票推举的(服务器 1)大,更改选票为推举服务器 2。此时服务器 1 的票数是 0 票,服务器 2 的票数是 2 票,两者都没有半数以上的票数,选举无法完成,服务器 1 和 服务器 2 的状态保持 LOOKING。

  • (3) 服务器 3 启动,发起一次选举。此时服务器 1 和 2 都会更改选票为服务器 3。此次投票结果:服务器 1 有 0 票,服务器 2 有 0 票,服务器 3 有 3 票。此时服务器 3 的票数已经超过半数,服务器 3 当选 Leader。服务器 3 将状态更改为 LEADING,服务器 1 和 服务器 2 将状态更改为 FOLLOWING。

  • (4) 服务器 4 启动,发起一次选举。此时服务器 1、2、3 已经不是 LOOKING 状态,不会再更改选票信息。交换选票信息后的结果:服务器 3 有 3 票,服务器 4 有 1 票。此时服务器 4 少数服从多数,更改选票信息为服务器 3,并将自己的状态更改为 FOLLOWING。

  • (5) 服务器 5 启动,跟服务器 4 一样更改选票信息为服务器 3,并将自己的状态更改为 FOLLOWING。

特别注意

一旦集群中已经存在 Leader 节点,后面加入集群的节点都只会成为 Follower 节点。

集群非第一次启动

  • (1) 当 ZooKeeper 集群中的任意一台服务器出现以下两种情况之一时,就会开始进入 Leader 选举:

    • 服务器初始化启动。
    • 服务器运行期间无法和 Leader 保持连接。
  • (2) 当一台服务器进入 Leader 选举流程时,当前集群也可能会处于以下两种状态之一:

    • 集群中本来就已经存在一个 Leader

      • 对于集群已经存在 Leader 的情况,当服务器试图去选举 Leader 时,会被告知当前服务器的 Leader 信息;对于该服务器来说,仅仅需要和 Leader 服务器建立连接,并进行状态同步即可。
    • 集群中确实不存在 Leader

      • 对于集群不存在 Leader 的情况,整个集群会进入选举流程。
      • 假设 ZooKeeper 集群由 5 台服务器组成,SID 分别为 1、2、3、4、5,ZXID 分别为 8、8、8、7、7, 并且此时 SID 为 3 的服务器是 Leader。在某一时刻,SID 为 3 和 5 的服务器出现故障,由于 Leader 挂掉了,因此开始进行 Leader 选举。SID 为 1、2、4 的服务器的最终投票情况如下:
      •   (EPOCH, ZXID, SID ) (EPOCH, ZXID, SID ) (EPOCH, ZXID, SID )
          (1, 8, 1)           (1, 8, 2)           (1, 7, 4)
        
      • 选举 Leader 的规则:①EPOCH 大的直接胜出     ②EPOCH 相同,ZXID(事务 ID)大的胜出     ③ZXID(事务 ID) 相同,SID(服务器 ID) 大的胜出
      • 选举 Leader 的结果:SID 为 2 的服务器会被选举 Leader,SID 为 1 和 4 的服务器作为 Follower。

集群选举机制总结

ZooKeeper 使用半数投票机制来实现选举,超过半数的投票通过,即通过。

  • 集群第一次启动时的选举规则

    • 投票过半数时,服务器 ID 大的胜出
  • 集群非第一次启动时的选举规则

    • (1) EPOCH 大的直接胜出
    • (2) EPOCH 相同,事务 ID(ZXID)大的胜出
    • (3) 事务 ID(ZXID)相同,服务器 ID(SID)大的胜出

ZooKeeper 最佳实践

生产环境部署多少个集群节点

在生产环境中,ZooKeeper 集群应该部署奇数个节点,这是考虑到 ZooKeeper 使用半数投票机制来实现选举,超过半数的投票通过即通过,其他考虑因素还有半数写入。生产最佳实践如下:

  • 10 台服务器:3 个 ZooKeeper 节点
  • 20 台服务器:5 个 ZooKeeper 节点
  • 100 台服务器:11 个 ZooKeeper 节点
  • 200 台服务器:11 个 ZooKeeper 节点

对于 ZooKeeper 集群,节点数多的好处是可以提高可靠性,其坏处是增加了通信延时。