Skip to content

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 停顿假设)。

关键证据 / 例子

  • 演进链:setnxsetnx + 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 事务/补偿。

关联

最近更新