基于本文回答

播面 播面

文图音视,全方位拆解八股文
0
评论

ZooKeeper 是如何解决脑裂问题的?

知识点图片

ZooKeeper 主要通过 ZAB 协议(ZooKeeper Atomic Broadcast) 结合 过半机制(Quorum)Epoch(纪元/时代) 概念来解决脑裂(Split-Brain)问题。

简单来说,ZooKeeper 宁可牺牲可用性(停止服务),也要保证数据的一致性(CP原则)。

以下是具体的解决机制详解:

1. 过半机制(Quorum / Majority)—— 物理层面的防线

这是防止脑裂最基础的数学保证。ZooKeeper 规定:任何事务的提交和 Leader 的选举,都必须得到集群中“过半数”节点的认可。

  • 公式: N/2+1N/2 + 1
  • 原理: 在一个集群中,不可能同时存在两个“过半数”的子集群。
    • 假设集群有 5 台机器。过半数是 3。
    • 如果网络断开,集群分裂成 A区(2台)和 B区(3台)。
    • B区: 拥有 3 台机器(满足过半),可以选举出 Leader 并正常工作。
    • A区: 只有 2 台机器(不满足过半),无法选举出 Leader,也无法处理写请求,这部分集群会自动进入不可用状态(只读或停止服务)。

结论: 物理上保证了同一时间只能有一个合法的 Leader 所在的集群在工作,从而避免了两个集群同时写入导致的数据冲突。


2. Epoch(纪元/任期)机制 —— 逻辑层面的防线

即使有过半机制,还存在一种特殊情况:“假死”的旧 Leader 复活

场景:

  1. Leader A 发生了 Full GC 或者网络瞬断,导致与 Follower 失去联系。
  2. Follower 认为 Leader A 挂了,于是发起重新选举,选出了新的 Leader B(且获得了过半支持)。
  3. 此时,Leader A 恢复了(GC结束或网络恢复),它并不知道自己已经被废黜了,还认为自己是 Leader,并试图处理客户端的写请求。这就是所谓的“僵尸 Leader”。

ZooKeeper 如何解决?
ZooKeeper 引入了 zxid(ZooKeeper Transaction Id),这是一个 64 位的数字。

  • 低 32 位: 单调递增的计数器。
  • 高 32 位: 代表 Epoch(纪元)

处理流程:

  1. 选举新 Leader 时: 新 Leader B 产生时,会生成一个新的 Epoch(比如从 Epoch 1 变为 Epoch 2)。
  2. 更新状态: 集群中过半的 Follower 会更新自己的 Epoch 为 2,并只听从 Epoch 2 的 Leader 指挥。
  3. 旧 Leader 复活: 旧 Leader A(处于 Epoch 1)恢复后,试图发送写命令给 Follower。
  4. 拒绝请求: Follower 发现 Leader A 发来的请求 Epoch 是 1,而自己已经是 Epoch 2 了。Follower 会拒绝该请求,并告知 Leader A:“你的朝代已经亡了”。
  5. 降级: Leader A 收到拒绝信息后,意识到自己过时了,于是自动降级为 Follower,并同步 Leader B 的数据。

3. 选举时的限制

在 Leader 选举阶段,ZooKeeper 也有策略防止数据丢失或脑裂后的数据回滚:

  • 选谁做 Leader? 并不是谁先发起谁就当选。节点在投票时,会优先投票给 zxid 最大(数据最新)的节点。
  • 这保证了新的 Leader 一定拥有旧集群中所有已经提交(Committed)的数据,避免了脑裂恢复后的数据不一致。

总结

ZooKeeper 解决脑裂的核心策略可以概括为:

  1. 不让两个 Leader 同时存在: 利用 过半机制,确保网络分区时,只有拥有多数派的那一边能工作,少数派直接“罢工”。
  2. 不让旧 Leader 捣乱: 利用 Epoch(纪元) 标识,给 Leader 颁发“身份证”。一旦新王登基(Epoch增加),旧王的命令立刻失效,防止“僵尸 Leader”导致的数据错乱。
00:00
00:00