P84 分布式锁:Redis 还是 Zookeeper?
面试题:分布式锁用 Redis 还是 Zookeeper?怎么选?
1. 两种实现
Redis 分布式锁
bash
SET lock:order:1001 uuid NX EX 30 # 原子:不存在才设置 + 过期时间java
// 生产直接用 Redisson
RLock lock = redissonClient.getLock("order:" + orderId);
lock.lock(30, TimeUnit.SECONDS);
try { /* 业务 */ } finally { lock.unlock(); }要点:
- 必须
NX + EX原子设置(防止死锁); - 释放要校验 value(防止误删别人的锁),用 Lua;
- 可重入(Redisson 内部 hash 计数)、自动续期(watchdog)。
Zookeeper 分布式锁
text
创建临时顺序节点 /lock/lock_0000000001
判断自己是否是最小节点:
是 → 拿到锁
否 → Watch 前一个节点,等它删除后再判断要点:
- 临时节点:客户端会话断开自动删除,天然防死锁;
- 顺序节点 + Watch 实现公平锁;
- 强一致(ZAB 协议),无过期时间误删问题。
2. 对比
| 对比项 | Redis | Zookeeper |
|---|---|---|
| 一致性 | 主从切换可能丢锁(AP 场景) | 强一致(CP) |
| 性能 | 高(内存、无重协商) | 较低(ZAB 同步、Watch) |
| 死锁处理 | 过期时间(可能提前释放/误删) | 会话超时自动删除临时节点 |
| 实现复杂度 | 简单,Redisson 开箱即用 | 相对复杂 |
| 可用性 | 高(主从/集群,但锁语义弱) | 需要 ZK 集群,脑裂处理 |
| 适用 | 高性能、允许极少概率锁失效 | 强一致、锁可靠性优先 |
3. 怎么选
- 大部分互联网业务用 Redis/Redisson:性能好、实现简单,锁偶尔失效(极端网络/主从切换)可接受,配合幂等兜底;
- 对一致性要求极高(如唯一资源的强互斥、分布式调度)用 ZK;
- 还有 etcd(Raft)作为中间选择,云原生场景常用。
4. 高频追问
- "Redis 锁的 master 宕机丢锁怎么办":Redlock(多实例投票)争议较大,生产多用"主从 + 哨兵 + 幂等兜底";
- "锁过期了业务还没执行完":Redisson watchdog 自动续期,或业务侧处理;
- "为什么要校验 value 再释放":防止自己的锁已过期被别的线程拿走,自己 unlock 把别人的锁删了。
一句话总结
Redis 锁(SETNX + Redisson)性能高、实现简单,适合大多数业务;Zookeeper 临时顺序节点强一致、天然防死锁,适合锁可靠性优先的场景;选型本质是"性能 vs 一致性"的取舍,配幂等兜底更稳。