Redis分布式锁的实现
说到分布式锁,绝对是面试中的高频考点。当面试官让你实现跨进程的资源互斥访问时,Redis分布式锁几乎是必答的方案。今天咱们就掰开了揉碎了讲讲它的实现细节和那些容易踩的坑。
为啥需要分布式锁? 想象一下:订单支付、库存扣减、优惠券发放...这些高并发场景下,多个服务实例同时操作共享资源,没锁控制不就乱套了吗?传统的单机锁在分布式系统面前直接失效,这就是分布式锁的用武之地。
普通SetNX实现及其隐患
最基础的玩法就是用Redis的SETNX命令(现在更推荐SET key value NX PX):
SET lock_key unique_value NX PX 30000
这条命令尝试设置一个键值对,如果键lock_key不存在(NX选项),就设置成功(获得锁),同时设置30秒的超时(PX 30000),防止客户端挂掉导致死锁。解锁时用Lua脚本保证原子性删除:
if redis.call("get",KEYS[1]) == ARGV[1] then
return redis.call("del",KEYS[1])
else
return 0
end
⚠️ 但这个方案有致命缺陷:
- 锁超时问题: 业务执行超过30秒,锁自动释放,其他客户端进来操作,资源一致性就崩了。
- 单点故障: 主从切换时,如果主节点锁信息没同步到从节点,新主节点可能把锁发给另一个客户端。

Redis官方方案:Redlock
为了解决单实例的可靠性问题,Redis作者提出了Redlock算法:
核心步骤:
- 获取当前时间(
start_time)。 - 按顺序向N个独立的Redis主节点(非集群模式)发送加锁命令(
SET NX PX),使用相同的键名和随机值,并设置一个远小于锁超时时间的网络超时(如5-50ms)。 - 当从超过半数(N/2 + 1) 的节点成功获得锁,且获取锁的总耗时小于锁的超时时间(
lock_timeout),才算真正获取成功。锁的有效时间为初始设置的有效时间减去获取锁的总耗时(lock_timeout - elapsed_time)。 - 如果加锁失败(未达到半数或超时),立即向所有节点发送解锁请求(Lua脚本)。
Redlock通过多节点部署分散风险,降低单点故障概率。但它依然不是银弹:
- 性能开销大: 操作多个节点,网络延迟增加。
- 争议仍存: 对时钟依赖性强,极端故障场景下仍有小概率问题(比如主节点崩溃后持久化未完成,新主节点缺失锁数据)。
锁续期:解决业务超时问题
为了防止业务没执行完锁提前过期,需要锁续期(WatchDog) 机制:
- 获取锁成功后,启动一个后台守护线程。
- 守护线程定期(比如在锁过期时间的1/3时)检查锁是否还在(即检查
lock_key对应的值是否还是自己设置的那个unique_value)。 - 如果还在,则重新设置锁的过期时间(
EXPIRE或PEXPIRE),进行“续租”。 - 业务执行完毕主动释放锁时,同时关掉对应的守护线程。
Java中的Redisson库就内置了看门狗机制,开箱即用。
💡 面试鸭资源福利: 2025年最新Java面试宝典在此,涵盖Redis、分布式、高并发等核心面试点,助你通关!
实现一个健壮的Redis分布式锁需要考虑超时、续租、容错、原子性等多方面问题。在实际项目中,优先推荐使用成熟的客户端库(如Redisson),它们已经封装好了这些复杂的逻辑,大大降低了使用门槛和出错概率。
需要购买【面试鸭】会员解锁海量真题库? 通过 面试鸭返利网 找到我,立享25元返利!海量大厂真题、详细题解、面试经验等你来拿,投资自己永远是最划算的选择!



