主题
Redis 分布式锁
一句话机制:利用 Redis 单线程串行执行的特性,用
SET key value NX EX抢占唯一标记实现跨 JVM 互斥;靠 uuid 防误删 + Lua 原子释放 解决安全性,靠看门狗续期解决锁提前过期。
不变量(必须成立的约束)
- 加锁 + 过期必须原子:用
SET lock uuid NX EX seconds(替代SETNX+EXPIRE两步,后者非原子,宕机会死锁)。 - 释放锁必须校验持有者:删除前比对 uuid,防止误删别人持有的锁。
- 删除必须原子:比对 uuid 与
del之间锁可能过期被别人抢走,需用 Lua 脚本把「判断+删除」合成原子操作。 - 锁需设合理过期时间;业务未执行完锁已过期 → 需看门狗(Redisson)自动续期。
- 多节点高可用可用 RedLock(向多数节点申请锁),但其正确性在分布式社区有争议(依赖时钟/GC 停顿假设)。
关键证据 / 例子
- 演进链:
setnx→setnx + expire(非原子,危险)→set nx ex(原子)→+ uuid 防误删→+ Lua 原子删除→Redisson 看门狗续期。 - 对比 ZooKeeper:Redis 性能好但可靠性弱(主从切换可能丢锁);ZK 靠临时节点+顺序节点,可靠性高但吞吐低。
- 典型坑:比较 uuid 后、删除前锁过期 → A 删了 B 的锁。
常见误解
- ❌「setnx 后 expire 就行」——两步非原子,若 setnx 后进程挂了,锁永不过期(死锁)。
- ❌「拿到锁直接 del 释放」——会误删他人锁(自己锁已过期被别人抢走);必须 uuid 校验。
- ❌「uuid 校验后 del 就安全」——校验与删除间仍有竞态窗口,必须用 Lua 合并为原子。
- ❌「RedLock 绝对安全」——RedLock 依赖时钟假设,在 STW/时钟跳变场景仍有争议,不是银弹。
- ❌「分布式锁能替代事务」——锁只保证互斥,不保证业务原子性,复杂一致仍需 DB 事务/补偿。
关联
- 来源:Redis常见面试题(老鱼干 Redis6 分布式锁章节最完整)
- 相关:Redis技术栈总览、概念卡片:Redis缓存与数据库一致性