深入理解 ZAB:ZooKeeper 原子广播协议的工作原理
目录
- ZAB 协议:ZooKeeper 如何做到高可用和强一致?🔒
- ZAB 协议的核心目标 🎯
- ZAB 协议的关键概念 💡
- ZAB 协议的运行阶段 🎬
- 阶段一:Leader 选举 (Leader Election) 🗳️
- 阶段二:发现与同步 (Discovery and Synchronization) 📡🤝
- 阶段三:广播 (Broadcast) 📢✅
- ZAB 协议如何保证一致性?🔒
- 总结:可靠的分布式协调基石 💎
🌟我的其他文章也讲解的比较有趣😁,如果喜欢博主的讲解方式,可以多多支持一下,感谢🤗!
其他优质专栏: 【🎇SpringBoot】【🎉多线程】【🎨Redis】【✨设计模式专栏(已完结)】…等
如果喜欢作者的讲解方式,可以点赞收藏加关注,你的支持就是我的动力
✨更多文章请看个人主页: 码熔burning
ZAB 协议:ZooKeeper 如何做到高可用和强一致?🔒
在使用 Apache ZooKeeper 时,我们知道它是一个分布式协调服务,常用于配置管理、命名服务、分布式同步(如分布式锁)、组服务等。ZooKeeper 能够提供高可用和一致性的服务,其核心秘诀就在于它内部实现的ZAB (ZooKeeper Atomic Broadcast) 协议。
ZAB 协议是专为 ZooKeeper 设计的一种崩溃可恢复的原子广播协议。它的主要目标是确保 ZooKeeper 服务的所有副本(称为 Peer
,包括 Leader 和 Follower)之间保持状态的一致性,并且所有对状态的更新(事务)都能够按照全局唯一的顺序被处理。
简单来说,ZAB 协议就是要解决如何在分布式环境中,让大家(ZooKeeper 的各个节点)对同一个事情(数据更新)达成一致意见,并且这个过程是可靠的,即使有节点崩溃了也能恢复。🤝
ZAB 协议的核心目标 🎯
ZAB 协议主要确保以下两点:
- 一致性 (Consistency): 保证所有正确的 ZooKeeper 节点都具有相同的系统状态副本。无论客户端连接到哪个节点,都能看到相同的数据。
- 全局有序性 (Global Ordering): 所有修改 ZooKeeper 状态的事务都会被赋予一个全局唯一的序列号,并且所有节点都会按照这个序列号的顺序来处理这些事务。
ZAB 协议的关键概念 💡
理解 ZAB 协议,需要先掌握几个核心概念:
- 原子广播 (Atomic Broadcast): ZAB 协议的核心思想。它保证了任何一个事务(对 ZooKeeper 状态的修改操作)要么被 ZooKeeper 集群中的所有节点都接受并处理,要么一个节点都不处理。并且,所有节点处理这些事务的顺序是完全一致的。想象一下电视直播,所有观众看到的画面内容和顺序都是一样的。📺
- 角色 (Roles): 在 ZooKeeper 集群中,节点主要有三种角色:
- Leader (领导者): 集群中只有一个 Leader,负责处理所有的写请求(状态修改)。它接收客户端的写请求,生成新的事务,并将事务广播给 Follower。📢
- Follower (跟随者): 负责同步 Leader 发来的事务,并将事务应用到自己的状态上。它处理客户端的读请求。👥
- Observer (观察者): 与 Follower 类似,也同步 Leader 发来的事务并应用到自己的状态上。但它不参与 Leader 选举和写请求的投票过程。主要用于扩展读性能。👀
- 事务 (Transaction): 对 ZooKeeper 状态的每一次修改操作都抽象为一个事务。例如,创建节点、删除节点、设置节点数据等都是事务。📝
- Zookeeper 事务 ID (ZXID): 每个事务都有一个唯一的 64 位数字标识,称为 ZXID。ZXID 是单调递增的,它保证了事务的全局顺序性。ZXID 的高 32 位通常代表 Leader 的周期(Epoch),低 32 位代表该 Epoch 内的事务序列号。🔢
- 周期 (Epoch): Leader 选举成功后,新的 Leader 会创建一个新的 Epoch。Epoch 是一个单调递增的数字,用来标识 Leader 的一个任期。每次发生 Leader 切换,Epoch 都会增加。Epoch 的作用是为了区分不同 Leader 任期内产生的事务。🗓️
- 过半机制 (Quorum): ZAB 协议基于过半机制来实现一致性和可靠性。任何一个写事务,都需要集群中半数以上的节点(包括 Leader 自己)成功接收并确认,Leader 才会提交这个事务。同样,Leader 的选举也需要获得过半节点的投票。🗳️
ZAB 协议的运行阶段 🎬
ZAB 协议的运行主要分为三个阶段:
阶段一:Leader 选举 (Leader Election) 🗳️
当 ZooKeeper 集群启动时,或者当前的 Leader 发生故障、网络中断时,集群会进入 Leader 选举阶段。
这个阶段的目标是从所有正常运行的节点中选举出一个新的 Leader。选举过程可能会比较复杂,但核心是基于某种规则(比如每个节点都会给自己投票,并向其他节点发送自己的投票信息,包括自己认为的 Leader 及其最新的事务 ID ZXID)进行协商,最终得票过半的节点成为新的 Leader。
新的 Leader 诞生后,会生成一个新的 Epoch,这个 Epoch 将作为后续事务 ZXID 的高 32 位。
阶段二:发现与同步 (Discovery and Synchronization) 📡🤝
新的 Leader 选举出来后,它并不知道其他 Follower 节点当前的状态是什么样的。有些 Follower 可能丢失了一些最新的事务,有些可能还停留在旧的 Leader 周期。
这个阶段的目标是让新的 Leader 和所有 Follower 达到一致的状态,特别是保证所有 Follower 都拥有 Leader 提议过的所有事务。
具体过程大致是:
-
新的 Leader 会与所有 Follower 建立连接。
-
Follower 会向 Leader 报告自己当前接收到的最新事务的 ZXID。
-
Leader 会根据 Follower 报告的 ZXID,找出 Follower 缺失的事务。
- 如果 Follower 的 ZXID 落后于 Leader,Leader 会将 Follower 缺失的事务发送给它进行同步。
- 如果 Follower 的 ZXID 甚至超前于 Leader (这在理论上不应该发生,但在某些极端情况下可能存在脏数据),Leader 会要求 Follower 回滚到 Leader 的最新状态。
-
Leader 需要等待过半的 Follower 完成同步,确保大多数节点的状态与 Leader 一致。
这个阶段非常重要,它保证了在开始处理新的写请求之前,集群中的大多数节点已经处于一个一致的、最新的状态。
阶段三:广播 (Broadcast) 📢✅
一旦过半的 Follower 与 Leader 完成同步,集群就进入了正常运行的广播阶段。
在这个阶段,Leader 开始接收客户端的写请求。对于每一个写请求,Leader 会执行以下操作:
- 生成新的事务: 将客户端的写请求转换为一个内部的事务对象,并分配一个新的、单调递增的 ZXID(新的 Epoch + 当前 Epoch 内的计数器)。
- 提议 (Propose): Leader 将这个新的事务提议给所有的 Follower。
- 广播 (Broadcast): Leader 将事务发送给所有连接的 Follower。
- 确认 (Acknowledge): Follower 收到事务提议后,会将其写入自己的事务日志,并向 Leader 发送一个确认 (ACK)。📝➡️👍
- 提交 (Commit): Leader 收到过半的 Follower 的确认后,认为这个事务已经被大多数节点接受, Leader 就会向所有 Follower 发送一个 Commit 命令。收到 Commit 命令的 Follower 会将事务应用到自己的内存状态中。Leader 自己也会将事务应用到自己的状态中。✨
整个广播过程是原子性的: 事务要么在所有节点上都提交,要么都不提交。并且,由于 ZXID 的全局有序性,所有节点都会按照 ZXID 的顺序来处理和应用事务,保证了状态的一致。
ZAB 协议如何保证一致性?🔒
ZAB 协议通过结合上述概念和阶段,保证了分布式环境下的数据一致性:
- Leader 选举和 Epoch: 每次 Leader 切换都引入新的 Epoch,保证了不同 Leader 周期产生的事务不会混淆。新的 Leader 会基于大多数节点的状态来确定从哪里开始新的 Epoch 和 ZXID,避免了脑裂问题导致的不同 Leader 提交冲突的事务。
- ZXID 的单调递增: 为每个事务提供了唯一的全局顺序标识,所有节点按序处理,保证了事务应用的顺序一致。
- 过半机制: 任何写操作的提交都依赖于过半节点的确认。这意味着如果一个事务被提交了,它就肯定存在于集群中至少过半的节点上。当发生故障需要选举新的 Leader 时,新的 Leader 一定是从拥有最新已提交事务(最高 ZXID)的节点中选出的,从而保证了新的 Leader 的状态包含了所有已提交的事务。即使旧的 Leader 提议了某个事务但未获得过半确认就崩溃了,新的 Leader 也不会提交那个未完成的事务。半数以下的节点崩溃不会影响服务的可用性。💪
总结:可靠的分布式协调基石 💎
ZAB 协议是 ZooKeeper 能够提供可靠的分布式协调服务的基石。它通过 Leader 选举、基于 Epoch 和 ZXID 的事务排序、以及原子广播和过半机制,巧妙地解决了分布式环境下的数据一致性和可靠性问题。
理解 ZAB 协议对于深入学习 ZooKeeper、设计和实现高可用的分布式系统都非常有帮助!虽然它的细节实现比较复杂,但掌握其核心思想和工作流程,能让你更好地理解 ZooKeeper 的行为和性能。😊