ZooKeeper是如何保证一致性的?
ZooKeeper 保证一致性的核心机制在于 ZAB 协议 (ZooKeeper Atomic Broadcast)。
简单来说,ZooKeeper 通过单一的主节点(Leader)来处理所有写操作,并使用ZAB 协议将数据变更以事务日志的形式广播给所有从节点(Follower),只要有半数以上(Quorum)的节点确认,该变更就会被提交。
以下是 ZooKeeper 保证一致性的详细技术实现:
1. 核心协议:ZAB (ZooKeeper Atomic Broadcast)
ZAB 协议是 ZooKeeper 专门设计的一种支持崩溃恢复的原子广播协议。它主要有两种模式:
- 崩溃恢复模式 (Recovery Mode): 当集群启动或 Leader 宕机时进入此模式。
- 选举 Leader: 选举出一个新的 Leader。为了保证数据一致性,被选出的 Leader 必须拥有集群中最大 ZXID(即数据最新)。
- 数据同步: 新 Leader 会将自己的数据同步给所有 Follower,确保集群达到一致状态后,才开始对外服务。
- 消息广播模式 (Broadcast Mode): 当集群状态正常时,进入此模式处理写请求。
- 这是一个类似于 两阶段提交 (2PC) 的过程,但移除了中断逻辑(只要半数通过即可,不需要全部通过)。
2. 全局唯一事务 ID:ZXID
为了保证事务的顺序一致性,ZooKeeper 为每一个写操作分配一个全局唯一的 ID,称为 ZXID (ZooKeeper Transaction Id)。
- ZXID 是一个 64 位的数字。
- 高 32 位 (Epoch): 代表 Leader 的纪元(类似朝代)。每换一次 Leader,Epoch 加 1。这保证了旧 Leader 即使复活也无法干扰新集群。
- 低 32 位 (Counter): 是一个递增计数器。
- 作用: 通过 ZXID,ZooKeeper 能够严格识别出操作的先后顺序。
3. 写操作的一致性流程 (Write Path)
所有的写请求(create, setData, delete)无论发送给哪个节点,最终都会被转发给 Leader 处理。流程如下:
- Proposal (提案): Leader 收到写请求,生成一个新的 ZXID,将请求封装成一个事务 Proposal,并写入本地事务日志。
- Broadcast (广播): Leader 将 Proposal 广播给所有 Follower。
- ACK (确认): Follower 收到 Proposal 后,将其写入本地事务日志,成功后向 Leader 返回 ACK。
- Commit (提交): 一旦 Leader 收到超过半数 (Quorum) 节点的 ACK,它就认为该提案通过。
- Leader 向所有 Follower 发送 Commit 消息。
- Leader 自己执行 Commit,将数据应用到内存数据库,并响应客户端。
- Apply: Follower 收到 Commit 消息后,也将数据应用到内存中。
4. 读操作的一致性 (Read Path)
这是 ZooKeeper 一致性模型中容易被误解的地方:
- 顺序一致性 (Sequential Consistency): ZK 保证客户端看到的更新顺序与发送顺序一致。
- 读操作不经过 Leader: 客户端可以连接任意 Follower 读取数据。
- 可能存在“脏读” (Stale Reads): 由于网络延迟,Follower 收到 Commit 的时间可能比 Leader 晚。因此,客户端在 Follower 上可能读到稍旧的数据。
- 如何保证强一致性读?
- 如果客户端必须读取最新数据,需要在读取前执行
sync()命令。这会强制 Follower 与 Leader 进行同步,然后再返回结果。
- 如果客户端必须读取最新数据,需要在读取前执行
5. 具体的保证 (Guarantees)
ZooKeeper 官方文档定义了以下一致性保证:
- 顺序一致性: 来自客户端的更新将按发送顺序被应用。
- 原子性: 更新要么成功,要么失败,没有中间状态。
- 单一系统映像 (Single System Image): 无论客户端连接到哪个服务器,看到的数据视图都是一样的(结合
sync理解,或者理解为不会看到回滚的数据)。 - 可靠性 (Durability): 一旦更新被应用,它将持久存在,直到被覆盖。
- 及时性 (Timeliness): 系统的客户视图保证在特定时间范围内是最新的(最终一致性的一种强形式)。
总结
ZooKeeper 通过 Leader 统一写操作、ZXID 保证全局顺序、ZAB 协议处理崩溃恢复和消息广播、以及 过半机制 (Quorum) 来保证分布式数据的一致性。它是一个 CP 系统(CAP 理论中优先保证一致性和分区容错性)。