redis分布式锁本质是用全局唯一key作占位符,通过set命令的nx/px选项实现互斥与防死锁,释放锁须用lua脚本原子校验clientid;redisson通过自动续期、可重入、阻塞等待等机制简化生产级使用。

Redis分布式锁本质是用一个全局唯一的key做“占位符”,谁设成功了,谁就拿到锁;关键是要设得安全、删得靠谱、扛得住宕机和网络波动。
基础实现:SET命令一步到位
最核心的命令就是:
- SET lock:order_123 clientA NX PX 30000 —— “只有key不存在时才设置,且30秒后自动过期”
- NX保证互斥(同一时间只有一个客户端能成功)
- PX防止死锁(服务崩溃也不怕锁永远卡住)
- clientA是唯一标识,后续释放锁时用来校验身份,避免误删
释放锁必须用Lua脚本
不能直接DEL,否则可能删掉别人正在用的锁。正确做法是用一段Lua脚本原子执行“先检查再删除”:
- 脚本内容:if redis.call("GET", KEYS[1]) == ARGV[1] then return redis.call("DEL", KEYS[1]) else return 0 end
- KEYS[1]是锁key,ARGV[1]是当前客户端的唯一标识(比如UUID)
- Redis单线程执行Lua,整个判断+删除过程不可打断,彻底杜绝竞态
Redisson是怎么简化这件事的
Redisson不是简单封装,而是补全了生产环境真正需要的能力:
- 自动续期(Watch Dog):加锁后默认每10秒检查一次,只要业务还在跑,就自动把锁有效期延长到30秒,不怕超时误释放
- 可重入:同一个线程再次加锁,会记录重入次数,解锁也按次数匹配,不会提前释放
- 阻塞等待:支持tryLock(5, TimeUnit.SECONDS),等5秒拿不到就放弃,不空转耗资源
- 异常自动清理:连接断开或节点故障时,Redisson能感知并尝试安全释放锁
几个容易踩的坑
不用Redisson自己写,这些点基本绕不开:
- SETNX + EXPIRE分开调用 → 崩溃在中间会导致无过期时间的死锁
- 用固定值当锁value(比如"1")→ 所有客户端都能删,完全失去安全性
- 没做锁续期 → 耗时操作超过过期时间,锁被自动释放,其他线程趁虚而入
- 主从架构下没考虑复制延迟 → 主库设了锁,从库还没同步就被读取,导致多个客户端同时认为自己拿到了锁(RedLock就是为解决这个设计的,但多数场景用单Redis+Redisson已足够)
基本上就这些。用好Redisson,95%的分布式锁需求都稳了;自己手写,重点盯住原子性、身份校验、自动续期这三点。










