分布式锁:四介质全景 + 安全性 checklist + 主从切换丢锁

microservice 📚 learning distributed-lock · distributed-lock · redis · zookeeper · etcd · redisson · lock · concurrency

TL;DR(30 秒扫完)

  • 四大介质:Redis / ZooKeeper / etcd / DB,各有取舍
  • 三维权衡:一致性(AP vs CP)/ 性能(毫秒 vs 十毫秒)/ 死锁友好度
  • 六条安全性 checklist:加锁原子性 / 持有者校验 / 过期时间 / watchdog / 可重入 / 锁粒度
  • 主从切换丢锁:Redis 最致命风险,业务侧幂等兜底 vs 换 ZK/etcd 强一致
  • RedLock 争议:Antirez 多节点方案 vs Marko Elezi 时钟偏移论证,主流不推荐

关键结论

结论 A分布式锁四大介质——Redis(AP 弱一致、高性能)/ ZK(CP 强一致、临时节点自动释放)/ etcd(CP Raft+Lease、K8s 生态)/ DB(CP 事务、零外部依赖但性能差)
结论 B三维权衡矩阵——一致性、性能、死锁友好度是选型核心
结论 C安全性 checklist 六条——加锁原子性、持有者校验、过期时间、watchdog、可重入、锁粒度缺一不可
结论 D主从切换丢锁是 Redis 锁最致命风险,兜底方案是业务侧幂等,不是 RedLock

完整讲解(费曼四步)

STEP 1 · 概念

分布式锁:在分布式环境下保证"同一时间只有一个节点持有锁"的机制,本质是"互斥 + 可观察的持有状态"。

STEP 2 · 大白话

类比会议室:
  • Redis 锁:像酒店前台的"占位卡"——快,但前台电脑崩溃时占位可能丢失(主从切换)
  • ZK 锁:像智能门锁——你离开自动释放锁(临时节点),非常可靠但开门慢一点
  • etcd 锁:像集群表决锁——多节点投票决定谁持有(Raft),K8s 首选
  • DB 锁:像纸质登记簿——最土但零依赖,SELECT FOR UPDATE 或 INSERT 唯一约束

STEP 3 · 底层

3.1 四大介质完整对比

介质实现机制一致性性能死锁友好度典型场景
RedisSET key value NX PX 30000 + Redisson watchdogAP(主从切换可能丢锁)高(毫秒)靠 watchdog 续期高并发业务锁
ZooKeeper临时顺序节点 + watch 前一个节点CP(ZAB 协议强一致)中(十毫秒)临时节点进程崩溃自动删除Leader 选举、强一致
etcdRaft 一致性 + Lease 租约 + WatchCP(Raft 共识)中高Lease TTL 自动续期K8s 生态、云原生
DBINSERT 唯一约束(乐观)/ SELECT FOR UPDATE(悲观)CP(事务保证)低(百毫秒+)需手动管理(无 watchdog)低频场景、已有 DB

3.2 安全性 checklist 六条

任何分布式锁实现都必须满足以下 6 条:
  • 加锁原子性:
  • Redis:SET key value NX PX 30000 一条命令原子执行"不存在才设置 + 过期时间"
  • ❌ 反例:先 SET 再 EXPIRE 两步操作,两步之间崩溃会导致永久锁
  • 持有者校验:
  • value 存请求者的 UUID 或线程 ID
  • 解锁必须用 Lua 脚本 if GET == mine then DEL 原子执行
  • ❌ 反例:分开执行 GET + DEL,中间锁刚好过期被其他客户端抢占,DEL 会误删别人的锁
  • 过期时间:
  • 防持锁进程崩溃导致死锁
  • 通常设 30 秒 + watchdog 续期
  • watchdog 续期:
  • Redisson 每 TTL/3 检查持锁线程是否存活
  • 存活则续期,崩溃则不续期让锁自然过期
  • 防止"业务卡住但锁持有"的死锁
  • 可重入:
  • 同线程多次加锁累加计数器(count++)
  • 释放时 count-- 归零才真正删除锁
  • 类似 ReentrantLock
  • 锁粒度设计:
  • 按业务对象锁,比如 lock:order:{orderId} 而不是全局锁
  • 全局锁会导致大量线程无谓等待

3.3 主从切换丢锁的完整场景

场景:Redis 主从架构下:
  • 客户端 A 在主库加锁 SET lock_a uuid_a NX PX 30000
  • 主库崩溃,还没同步到从库
  • 从库升主(新主库没有 lock_a)
  • 客户端 B 在新主库成功加锁 SET lock_b uuid_b NX PX 30000
  • A 和 B 同时持有"同一把锁"——违反互斥性!
兜底方案:
  • 业务侧幂等:接受 AP 弱一致性,靠业务幂等防止重复执行(推荐)
  • 换 ZK/etcd:需要强一致就用 CP 系统
  • RedLock 争议:Antirez 提过多节点多数派方案,但 Marko Elezi 论证客户端时钟偏移会导致失效,主流社区已经不推荐(Redisson 也弃用了)

3.4 场景选型矩阵

场景推荐介质原因
高并发业务锁(秒杀、库存扣减)Redis + Redisson性能好、AP 弱一致可接受、靠 watchdog 防死锁
Leader 选举ZK 或 etcdCP 强一致,进程崩溃自动释放
云原生 / K8s 生态etcdRaft + Lease + Watch,K8s 标配
低频场景 / 已有 DBDB零外部依赖,SELECT FOR UPDATE
金融强一致ZK 或 etcd一致性优先,不能用 Redis

STEP 4 · 简化(口诀)

四大介质:Redis 快(AP)/ ZK 稳(CP)/ etcd 云(Raft)/ DB 土(事务)
>
六条 checklist:加锁原子、持有校验、过期防死、watchdog 续、可重入计数、粒度业务化
>
主从切换兜底:业务幂等兜底(Redis)/ 换 ZK-etcd(强一致)/ RedLock 别用(争议)

延伸追问

Redis 分布式锁的解锁 Lua 脚本怎么写?为什么不能分开执行 GET + DEL?
要点:if redis.call('GET', KEYS[1]) == ARGV[1] then return redis.call('DEL', KEYS[1]) else return 0 end;分开执行会有竞态——GET 校验通过但 DEL 之前锁刚好过期被其他客户端抢占,DEL 会误删别人的锁
watchdog 机制具体如何工作?如果持锁线程 hang 死了怎么办?
要点:Redisson 启动独立看门狗线程,每 TTL/3 检查持锁状态;业务线程 hang 时 watchdog 仍能续期,业务侧需要超时兜底;业务进程崩溃 watchdog 也停,锁自然过期
分布式锁和幂等控制是什么关系?是重复的吗?
要点:分布式锁解决"并发互斥"(同时只能一个进),幂等解决"多次执行结果一致"(进了多次也要一致);两者互补——锁在入口防止重复进入,幂等在业务层兜底

速查表

四介质      · Redis 快 AP · ZK 稳 CP · etcd 云 Raft · DB 土事务
三维权衡    · 一致性 AP/CP · 性能 毫秒/十毫秒 · 死锁友好度 watchdog/临时节点
六条 checklist · 加锁原子 SET NX+PX · 持有校验 value+Lua · 过期时间防死
             · watchdog 每 TTL/3 续期 · 可重入 count 计数 · 粒度 lock:order:{id}
主从切换兜底 · Redis 靠业务幂等 · 强一致用 ZK/etcd · RedLock 有争议别用

Anki 候选卡片

Q: 分布式锁四大介质?
A: Redis(AP 高性能)/ ZK(CP 强一致)/ etcd(CP Raft+Lease)/ DB(CP 事务、性能低)
Q: Redis 分布式锁的加锁命令?
A: SET key value NX PX 30000——一条命令原子执行"不存在才设置 + 过期时间"
Q: 解锁为什么要用 Lua 脚本?分开 GET+DEL 有什么问题?
A: 分开执行会有竞态——GET 校验通过后锁刚好过期被其他客户端抢占,DEL 会误删别人的锁;Lua 脚本原子执行 if GET==mine then DEL
Q: Redisson watchdog 机制如何工作?
A: 独立看门狗线程每 TTL/3 检查持锁线程是否存活,存活续期、崩溃不续期让锁自然过期
Q: Redis 主从切换丢锁的完整场景?
A: 主库加锁崩溃 → 从库升主未同步到锁 key → 第二个客户端能加锁,违反互斥性
Q: 主从切换丢锁的兜底方案?
A: 业务侧幂等兜底(AP 弱一致)/ 换 ZK/etcd(CP 强一致)/ RedLock 有争议别用
Q: 分布式锁安全性 checklist 六条?
A: ① 加锁原子 SET NX+PX ② 持有者校验 value+Lua ③ 过期时间防死 ④ watchdog 续期 ⑤ 可重入 count 计数 ⑥ 锁粒度 lock:order:{id}
Q: RedLock 争议是什么?
A: Antirez 提多节点多数派方案,Marko Elezi 论证客户端时钟偏移会导致失效,主流不推荐(Redisson 弃用)
Q: 分布式锁和幂等的关系?
A: 互补不重复——锁解决"并发互斥"(同时只能一个进),幂等解决"多次执行结果一致"(进了多次也要一致)
Q: 分布式锁场景选型?
A: 高并发业务锁→Redis+Redisson / Leader 选举→ZK 或 etcd / 云原生→etcd / 低频→DB / 金融强一致→ZK 或 etcd

关联题目

  • [ ] 《分布式锁有几种实现方式?》—— 2026-10-08 Round 1 Q4, 评分 ⭐⭐⭐
  • [ ] 《实现一个分布式锁需要考虑哪些问题?》—— 2026-10-08 Round 1 Q5, 评分 ⭐⭐⭐⭐
  • [ ] 《Redis 分布式锁和 Zookeeper 分布式锁有啥区别?》—— 待考
  • [ ] 《如何用 Redisson 实现分布式锁?》—— 待考

关联知识

四大介质 Redis/ZK/etcd/DB 三维权衡 + 六条安全性 checklist + 主从切换丢锁靠业务幂等兜底
酒店前台占位卡(Redis 快但可能丢)vs 智能门锁(ZK 可靠但慢)vs 集群表决锁(etcd Raft)vs 纸质登记簿(DB 土)
✦ 记 忆 口 诀 ✦
Redis 快 AP / ZK 稳 CP / etcd 云 Raft / DB 土事务
关键可视化
暂无可视化
知识关系

⬆️ 前置(Prerequisite)

../microservice/resilience-patterns.md

🔄 延伸(Extends)

../redis/cache-three-failures.md

⚡ 对比(Contrast)

暂无
🎯 概念 📏 规则 ⚠️ 误区 🔍 追问 ✨ 口诀 共 0 张卡,点击翻面