redis分布式锁防误删需加锁释放均原子化:加锁用set key value nx px防止死锁,value为唯一标识;释放锁必须lua脚本校验value再删除;生产推荐redisson,自动续期、可重入且安全可靠。

Redis 实现分布式锁并防止锁误删,核心在于两点:加锁时保证原子性 + 释放锁时验证所有权。不是简单设个 key 再 del 就完事,否则极易出现 A 持有锁但超时释放后,B 加锁成功,A 却仍执行 DEL 把 B 的锁删掉——这就是典型的“误删”。
加锁必须一步到位,带值、带过期、带互斥
用 Redis 的 SET 命令一次性完成三件事:设值、检查不存在、设置过期时间。不能拆成 SETNX + EXPIRE,那不是原子操作,中间崩溃就会留“死锁”。
-
命令示例:
SET lock:order:1001 "8f3a2b9c" NX PX 30000 - NX 确保只有 key 不存在时才成功,实现互斥
- PX 30000 设置 30 秒自动过期,防服务宕机导致锁永久占用
- value 必须是全局唯一随机串(如 UUID),后续释放时用来校验身份,这是防误删的前提
释放锁必须原子验证 value 再删除
不能先 GET 再 DEL——这两步之间可能被其他客户端插队。必须用 Lua 脚本把“读值→比对→删键”打包成一个不可分割的操作。
- Lua 脚本内容: if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end
- KEYS[1] 是锁 key(如
lock:order:1001),ARGV[1] 是你加锁时用的 value(如"8f3a2b9c") - 脚本在 Redis 内部执行,全程无网络中断或并发干扰,100% 原子
- 返回 1 表示删除成功,0 表示 value 不匹配(锁已不属于你,或已被释放)
生产环境建议直接用 Redisson
自己手写加锁/解锁逻辑容易漏细节(比如锁续期、可重入、主从脑裂处理)。Redisson 是 Redis 官方推荐的 Java 客户端,已内置健壮实现:
- 调用
lock.tryLock(10, 30, TimeUnit.SECONDS)即可尝试获取锁,含等待和自动续期 - 内部自动启用“看门狗”机制:只要业务还在跑,就每 10 秒把锁有效期重置为 30 秒
- unlock() 会自动走 Lua 校验,无需手动拼脚本
- 支持可重入、公平锁、联锁等进阶特性,省心且可靠











