Files
autumn-recruitment/05.架构/distributed-lock/ZooKeeper 分布式锁_test.md
T

147 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
tags: [test/review, architecture, arch/distributed, zookeeper-distributed-lock]
create time: 2026-08-09 12:00
---
# ZooKeeper 分布式锁 — 测试题
## 概述
本测试覆盖 ZooKeeper 分布式锁的核心机制,包括临时顺序节点创建、Watch 一次性触发、公平锁实现原理、ZAB 协议 CP 保证以及与 Redis 锁的系统级对比。共 10 道题目(6 选择 + 3 填空 + 1 简答)。
---
## 一、选择题(6道,由浅入深)
> **难度阶梯**: Q1-Q2 基础概念 → Q3-Q4 核心原理 → Q5-Q6 深入应用/边界场景
### Q1(基础)— 考察定义层面
ZK 分布式锁中创建节点的类型是什么,使得客户端断开连接后能自动清理锁?
A. PERSISTENT — 持久节点,需手动删除
B. EPHEMERAL_SEQUENTIAL — 临时顺序节点
C. PERSISTENT_SEQUENTIAL — 持久顺序节点
D. EPHEMERAL — 临时节点但无序号
### Q2(基础)→
以下关于 ZK Watch 机制的说法中,哪一个是正确的?
A. Watch 被触发后会保持注册,持续监听后续变化
B. Watch 是一次性的(One-shot),触发后需要重新注册
C. Watch 只在 `getData` 调用时才会注册
D. Watch 事件通过数据读取通道推送,确保顺序性
### Q3(进阶)— 核心原理
ZK 分布式锁天然实现了公平性,其根本原因是什么?
A. Leader 节点按 FIFO 队列分配锁
B. 使用 SEQUENTIAL 序号决定锁的持有权,按序号大小排序
C. Watch 事件按时间戳排序后分发给等待者
D. ZAB 协议保证了写操作的原子性和有序性
### Q4(进阶)— 比较/辨析
Redis 锁 vs ZK 锁在一致性模型上的主要区别是:
A. Redis 和 ZK 都是 AP 系统
B. Redis 是 CP,ZK 是 AP
C. Redis 单实例是 AP(Redlock 不确定),ZK 是 CP(ZAB 强一致)
D. Redis 是 CP,ZK 是不确定的
### Q5(深入)— 场景推理
N = 3 的 ZK 集群遭遇网络分区,左右各有一个节点。以下描述正确的是:
A. 两边都能正常工作,各自选出新 Leader
B. 左边可以继续写,右边拒绝服务
C. 都无法达成 Quorum,全部停止工作
D. 自动合并为 N=2 集群继续服务
### Q6(深入)— 源码级/边界场景
ZK 会话超时默认 40 秒太长了。根据原文建议,会话超时应该设为多少?同时心跳间隔与会话超时的关系是什么?
A. 建议 1~5 秒;heartbeat = timeout / 5
B. 建议 3~10 秒;heartbeat = timeout / 3
C. 建议 5~15 秒;heartbeat = timeout / 2
D. 建议 10~30 秒;heartbeat = timeout / 4
---
## 二、填空题(3道)
### F1 — 填空1
ZK 分布式锁使用的事件类型是 _____,当子节点列表发生变化时,所有相关监听者都会收到通知。
> **提示**: 这个事件的英文命名直接表达了"节点子列表变化"的含义。
### F2 — 填空2
ZAB 协议的第一个核心阶段是 _____,通过比较 ZXID(事务 ID)选出拥有最大 ZXID 的节点作为 Leader。第二个阶段是 Atomic Broadcast。
> **提示**: 回想 ZAB 的两个核心阶段名称。
### F3 — 填空3
Curator 是 ZK 最流行的 Java 客户端,加锁成功后需要在 finally 块中调用 _____() 方法。该方法会递归释放所有重入计数,而不仅仅是一次 unlock。
> **提示**: Curator 的方法名不是简单的 unlock,而是表达"释放锁"的动作。
---
## 三、简答题(1道)
### S1
某团队正在选型分布式锁方案,有人主张:"ZK 锁比 Redis 锁高级,我们应该用 ZK。"请结合原文内容,从以下几个维度给出你的分析并做出选型建议:
- 一致性要求
- 性能需求
- 运维复杂度
- 业务场景匹配度
> **答题框架提示**:
> 1. 先反驳"更高级就更好"的思维误区
> 2. 从三个维度客观对比
> 3. 给出具体场景下的推荐方案
---
## 参考答案与解析
### 选择题答案
| 题号 | 正确答案 | 解析 |
|------|---------|------|
| Q1 | B | EPHEMERAL_SEQUENTIAL = 临时 + 顺序。EPHEMERAL 语义保证 session 断开时自动清理,SEQUENTIAL 提供全局有序性。D 选项 EPHEMERAL 虽然也会自动清理,但没有序号就无法实现公平锁。 |
| Q2 | B | Watch 是一次性的,触发后自动注销。客户端必须在接收到事件后立刻重新注册,否则可能永远不再收到下一次通知。 |
| Q3 | B | 因为节点是 SEQUENTIAL 的,按序号大小决定锁的持有权——最小序号获得锁,其他节点按从小到大依次监听前一个节点。这是天然 FIFO 公平性。 |
| Q4 | C | Redis 单实例是 AP(追求高可用),Redlock 的一致性甚至不确定;ZK 基于 ZAB 协议是 CP(追求强一致性),脑裂时宁可停服也不会出现两把锁同时存在。 |
| Q5 | C | N=3 时 Quorum = 2。每个分区只有 1 个节点,无法达到半数(≥2),所以两个分区都无法工作。这是 CP 系统的必然结果——安全性优先于可用性。 |
| Q6 | B | 建议设为 3~10 秒以更快感知宕机。但 heartbeat interval = timeout / 3,太短的 timeout 会导致心跳过于频繁增加网络开销。 |
### 填空题答案
| 题号 | 答案 | 解析 |
|------|------|------|
| F1 | `NodeChildrenChanged` | ZK 锁场景下关注的是子节点列表的变化。当上一个持有者删除节点后,下一个等待者的 watch 会收到 NODE_DELETED 事件进而 getChildren 重新竞争。 |
| F2 | `Leader Election` | ZAB 的两阶段:① Leader Election 选举 Leader;② Atomic Broadcast Leader 广播 Proposal,Follower 回复 ACK 达到半数后提交。 |
| F3 | `release` | Curator 的 InterProcessMutex.acquire() 支持重入,release() 会递归递减重入计数直到归零才真正发送删除请求。直接用 delete 会导致重入计数未释放。 |
### 简答题参考答案
S1:**参考答案要点**:
1. **"更高级"思维误区**:ZK 不是为"高级"设计的,而是为"强一致性协调"设计的。不要因为技术栈偏好而引入不必要的复杂度。
2. **一致性维度**:如果业务只需要简单互斥(如防止用户重复点击),Redis SET NX 足够好,CP 过度设计。如果需要 Leader 选举等强一致性保证,ZK 更适合。
3. **性能维度**:Redis 百万级 QPS(内存操作),ZK 需写事务日志同步复制,QPS 低一个数量级。高频短锁场景 Redis 明显更优。
4. **运维维度**:Redis 集群工具链成熟,ZK 需要维护奇数节点集群,运维成本高。
5. **结论**:简单互斥 → Redis + SET NX EX;强一致性少量并发控制(Leader 选举、Job 唯一绑定)→ ZK;不要为了"更高级"而上 ZK。
**评分标准**:答出任意 2 个要点即可得满分;完全正确需覆盖全部要点。
## 关联笔记
- [[Redis 分布式锁]]
- [[幂等设计方案]]