很多后端工程师觉得“加个 Redis 锁”就安全了,其实绝大部分用法都不正确,会导致:
- 锁提前释放
- 业务误判
- 多实例同时执行
这篇文章讲一下我实施过最安全、最常用的 Redis 分布式锁方案。
一、常见错误用法
SET key value NX EX 30
然后执行完:
DEL key
问题:
- 如果业务超时超过 30s?锁过期提前释放
- 删除时没有判断 value 是否匹配 → 可能删了别人持有的锁
二、正确用法:value 作为 token
const token = uuid()
SET lock token NX PX 30000
执行完释放锁:
-- Lua 脚本保证原子性
if redis.call("get", KEYS[1]) == ARGV[1] then
return redis.call("del", KEYS[1])
else
return 0
end
Node.js 写法:
redis.eval(luaScript, 1, key, token)
三、锁续期机制(Watchdog)
业务超过 30s 怎么办?需要续期线程:
- 在锁快过期前(如 20 秒)
- 自动执行
PEXPIRE
例如:
setInterval(() => {
redis.pexpire(key, 30000)
}, 20000)
四、哪种场景必须使用分布式锁?
- 秒杀库存扣减
- 同一业务只允许一个实例执行(如报表生成)
- 限制用户频繁操作
- 防重入
五、总结
安全分布式锁必须满足:
- 互斥
- 不丢锁
- 不误删
- 可续期
- 自动释放
Redis + Lua + Token 的方案是目前最稳的方式之一。