1.ZooKeeper 核心知识梳理:从基础概念到 ZAB 协议

65 阅读7分钟

在分布式系统中,协调服务是保障数据一致性、集群稳定性的关键,而 ZooKeeper 正是这类场景的经典工具。这篇文章整理自我的学习笔记,聚焦 ZooKeeper 的核心概念、系统特性与底层协议,适合用于知识复盘或体系化梳理,若能为你提供参考,我会十分荣幸。

一、先搞懂:ZooKeeper 是什么?

ZooKeeper 是一款分布式应用程序协调服务,基于分布式数据一致性方案,能帮我们解决分布式系统中的常见问题,比如:

  • 数据发布 / 订阅、负载均衡、命名服务
  • 分布式协调 / 通知、集群管理、Master 选举
  • 分布式锁、分布式队列

二、核心基础:ZooKeeper 的关键概念

要用好 ZooKeeper,必须先掌握它的几个核心概念,这些是理解其工作原理的基础。

1. 角色:集群的 “分工合作”

ZooKeeper 集群由 3 类角色组成,各自职责明确:

  • Leader(领导者) :集群的核心,负责发起投票、决议事务(如数据更新),并同步状态到其他节点;

  • Learner(学习者) :分为 Follower 和 Observer,辅助 Leader 工作:

    • Follower:接收客户端读请求并返回结果,参与 Leader 选举投票,同时同步 Leader 的事务数据;
    • Observer:仅接收读请求、转发写请求给 Leader,不参与投票,主要作用是扩展集群读能力、减轻 Follower 压力;
  • Client(客户端) :发起请求的一方(如读写数据、注册监听),通过 TCP 长连接与集群交互。

2. 会话(SESSION):客户端与集群的 “连接纽带”

  • 客户端启动时,会与 ZooKeeper 服务器建立TCP 长连接(默认端口 2181),会话从连接建立时开始;
  • 客户端通过 “心跳检测” 维持会话有效性,可发送请求、接收响应,也能接收服务器的 Watch 事件通知;
  • 若连接异常断开,只要在sessionTimeout时间内重连集群任意一台服务器,会话依然有效。

3. 数据节点(Znode):ZooKeeper 的数据载体

ZooKeeper 的 data 模型是一棵 “Znode 树”,所有数据存储在内存中,核心特点如下:

  • 定义:以斜杠(/)分隔的路径就是一个 Znode(如/app/config),每个 Znode 既存数据,也存自身属性(如版本、权限);
  • 分类:节点分 “机器节点”(构成集群的服务器)和 “数据节点(Znode)”(存储数据的单元),我们通常讨论的是后者。

4. 版本:Znode 的 “数据变更记录”

每个 Znode 对应一个stat数据结构,其中维护 3 个关键版本,用于控制数据一致性:

  • version:Znode 自身数据的版本,数据更新一次就 + 1;
  • cversion:Znode 子节点的版本,子节点增删时 + 1;
  • aversion:Znode 的 ACL(权限)版本,权限变更时 + 1。

5. Watcher:Znode 的 “事件监听器”

  • 客户端可在指定 Znode 上注册 Watcher,当 Znode 发生特定事件(如数据变更、子节点增删)时,ZooKeeper 会主动通知客户端;
  • 注意:Watcher 是 “一次性” 的,触发后需重新注册才能继续监听。

6. ACL:Znode 的 “权限控制”

ZooKeeper 通过 ACL(Access Control Lists)控制 Znode 的访问权限,定义了 5 种核心权限:

  • CREATE:创建子节点的权限;
  • READ:获取 Znode 数据和子节点列表的权限;
  • WRITE:更新 Znode 数据的权限;
  • DELETE:删除子节点的权限;
  • ADMIN:修改 Znode ACL 权限的权限。

三、核心特性:ZooKeeper 的 “一致性保障”

作为分布式协调工具,ZooKeeper 能保证 5 大分布式一致性特性,这是其可靠性的核心:

  1. 顺序一致性:同一客户端发起的事务请求,会严格按发起顺序被应用;
  2. 原子性:事务请求的结果在集群中 “全有或全无”—— 要么所有机器都应用,要么都不应用;
  3. 单一视图:客户端无论连接集群哪台服务器,看到的数据模型都是一致的;
  4. 可靠性:事务一旦被成功应用,其状态变更会永久保留,除非被其他事务修改;
  5. 实时性:客户端能在 “一定时间内” 读取到最新数据,并非严格实时,但能满足绝大多数分布式场景需求。

四、设计目标:ZooKeeper 的 “设计初心”

ZooKeeper 的设计围绕 4 个核心目标,决定了它的适用场景:

  1. 简单的数据模型:以 Znode 树为核心,直观易懂,降低分布式协调的复杂度;
  2. 可构建集群:集群中超过半数机器正常,就能对外服务(如 3 台机器允许 1 台故障,5 台允许 2 台故障),保证高可用;
  3. 顺序访问:对每个更新请求分配全局唯一的递增编号(zxid),反映事务的先后顺序;
  4. 高性能:全量数据存于内存,非事务请求(如读操作)直接从内存响应,适合 “读多写少” 的场景。

五、底层核心:ZAB 协议如何工作?

ZooKeeper 的一致性依赖ZAB 协议(ZooKeeper Atomic Broadcast,原子广播协议),它是支持 “崩溃恢复” 的原子广播协议,核心是 “主备模型”—— 由 Leader 协调事务,Follower 同步数据。

1. ZAB 协议的核心逻辑

所有改变 ZooKeeper 数据状态的事务请求,都按以下流程处理:

  1. 客户端的事务请求(如写数据)统一发送给 Leader;
  2. Leader 将请求转换为 “事务 Proposal”,分发给所有 Follower;
  3. Leader 等待 Follower 反馈,当超过半数 Follower 确认(ACK)后,Leader 向所有 Follower 发送 “Commit” 消息;
  4. Follower 收到 Commit 后,提交该 Proposal,完成数据同步。

2. ZAB 的两种模式:崩溃恢复与消息广播

ZAB 协议通过两种模式保障集群一致性,切换逻辑如下:

  • 模式 1:崩溃恢复(选主模式)

    • 触发场景:集群启动、Leader 崩溃或网络分区导致 Leader 失联;
    • 核心目标:选举新 Leader,并保证新 Leader 拥有集群中 “最新的事务数据”,同时让所有 Follower 同步到最新状态;
    • 结束条件:新 Leader 选举成功,且超过半数 Follower 完成状态同步。
  • 模式 2:消息广播(同步模式)

    • 触发场景:崩溃恢复模式结束后,集群进入稳定状态;
    • 核心目标:处理客户端的事务请求,通过原子广播将事务同步到所有 Follower,保证数据一致性;
    • 新节点加入:若新服务器加入稳定集群,会先进入 “数据恢复模式”,同步 Leader 的最新数据后,再参与消息广播。

3. 关键设计:ZXID 与事务一致性

为保证事务的顺序和一致性,ZAB 协议引入了ZXID(事务 ID) ,这是一个 64 位的数字,结构如下:

  • 高 32 位:epoch(Leader 周期编号)—— 新 Leader 选举成功后,epoch会 + 1,用于区分不同 Leader 周期;
  • 低 32 位:单调递增的计数器 ——Leader 每生成一个新 Proposal,计数器就 + 1。

ZXID 的核心作用:

  1. 区分 Leader 周期:避免不同 Leader 使用相同 ZXID 提交不同事务;
  2. 保证事务顺序:Proposal 按 ZXID 递增顺序处理,确保因果关系;
  3. 崩溃恢复时的 “数据校验” :新 Leader 必须是集群中 ZXID 最大的节点 —— 这能保证新 Leader 拥有所有已提交的事务,无需额外检测 “哪些事务需要提交 / 丢弃”。

如何处理 “未提交的事务”?

若 Leader 在发送 Commit 前崩溃,部分 Follower 可能已确认 Proposal 但未提交,ZAB 通过以下逻辑保证一致性:

  • 新 Leader 选举后,会对比所有 Follower 的 ZXID;
  • 要求 Follower “回退” 到 “集群中过半机器已提交的最新事务”,丢弃未被多数节点确认的 Proposal,最终所有节点状态一致。

总结

ZooKeeper 的核心价值在于 “简单的数据模型 + 可靠的一致性保障”,无论是集群角色分工、Znode 的设计,还是 ZAB 协议的底层逻辑,都围绕 “分布式协调” 这一目标展开。掌握这些核心知识,不仅能更好地使用 ZooKeeper 解决实际问题,也能加深对分布式一致性原理的理解。