Redis缓存击穿时,分布式锁导致死锁,如何有效解除?

2026-05-07 15:560阅读0评论SEO基础
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计575个文字,预计阅读时间需要3分钟。

Redis缓存击穿时,分布式锁导致死锁,如何有效解除?

基本原因在于锁的释放逻辑和持有者不匹配,或者锁未设置过期时间。例如,使用SETNX和EXPIRE两步操作时,如果SETNX成功但后续过程崩溃或网络中断,EXPIRE将不会执行,导致锁永久存在于Redis中。另外,业务代码异常未执行DEL操作,也会导致锁残留。

加锁必须带原子性+自动过期

避免手动分两步设锁和过期,直接用原子命令:

  • SET key value EX seconds NX(推荐)—— 一条命令完成「不存在才设值 + 设置过期」
  • 不要用 SETNX 后再 EXPIRE,这两步非原子,中间出错就留孤儿锁
  • value 必须是唯一标识(如 UUID 或服务实例 ID),不能写死成 "1",否则释放时无法校验归属

释放锁必须校验 ownership

只靠 DEL key 是危险的:A 拿到锁,B 在 A 还没释放时误删了它,后续并发就失控了。正确做法是用 Lua 脚本做原子校验:

if redis.call("get", KEYS[1]) == ARGV[1] then return redis.call("del", KEYS[1]) else return 0 end

这个脚本确保只有持锁者才能删锁。对应 Java 工具类中 releaseLock(String key, String value) 的实现必须走这个逻辑,不能简单调 jedis.del(key)

阅读全文
标签:Redisred

本文共计575个文字,预计阅读时间需要3分钟。

Redis缓存击穿时,分布式锁导致死锁,如何有效解除?

基本原因在于锁的释放逻辑和持有者不匹配,或者锁未设置过期时间。例如,使用SETNX和EXPIRE两步操作时,如果SETNX成功但后续过程崩溃或网络中断,EXPIRE将不会执行,导致锁永久存在于Redis中。另外,业务代码异常未执行DEL操作,也会导致锁残留。

加锁必须带原子性+自动过期

避免手动分两步设锁和过期,直接用原子命令:

  • SET key value EX seconds NX(推荐)—— 一条命令完成「不存在才设值 + 设置过期」
  • 不要用 SETNX 后再 EXPIRE,这两步非原子,中间出错就留孤儿锁
  • value 必须是唯一标识(如 UUID 或服务实例 ID),不能写死成 "1",否则释放时无法校验归属

释放锁必须校验 ownership

只靠 DEL key 是危险的:A 拿到锁,B 在 A 还没释放时误删了它,后续并发就失控了。正确做法是用 Lua 脚本做原子校验:

if redis.call("get", KEYS[1]) == ARGV[1] then return redis.call("del", KEYS[1]) else return 0 end

这个脚本确保只有持锁者才能删锁。对应 Java 工具类中 releaseLock(String key, String value) 的实现必须走这个逻辑,不能简单调 jedis.del(key)

阅读全文
标签:Redisred