Redisson 分布式锁实现:可重入与看门狗

引言

在分布式架构中,多台服务器共享同一资源时,传统的 JVM 锁已无法保障数据一致性,分布式锁由此成为关键。Redisson 基于 Redis 实现的分布式锁,不仅支持可重入、自动续期,还通过发布订阅机制高效处理锁竞争。本文从加锁、锁续命、锁释放三个环节,深入解析 Redisson 的核心设计,包括 Lua 脚本保证原子性、Watch Dog 看门狗的定时续期机制,以及如何灵活控制锁的失效策略。

Redisson分布式锁实现

分布式锁是为了解决分布式架构中多台服务器共享资源的并发问题,单体时代可以使用JVM锁解决并发问题,但分布式架构中,同时存在多台服务器执行同样的逻辑,也就是在多套JVM环境下执行同样的逻辑,此时JVM锁无法生效,所以需要分布式锁。

加锁过程

还未加锁

  1. 先判断是否存在key为KEYS[1]的键值对(==0表示不存在),如果不存在表示未加锁。

  2. 通过hset(Hash结构)设置<锁名称, <UUID + 线程ID, 1>>,KEYS[1] = 锁名称,ARGV[2] = UUID + 线程ID。

  3. 通过pexpire设置key的过期时间,默认30s。

已经加锁

  1. 通过hexists(Hash结构)判读前线程是否加锁成功,如果当前线程加锁成功走2。

  2. 给当前线程的value+1。

  3. 在次通过pexpire设置key的过期时间,默认30s。

加锁失败

  1. 通过ttl返回剩余过期时间,方便后续线程重试去竞争锁,如果加锁成功则返回null。

  2. 加锁失败后会订阅频道(redisson_lock__channel + lockName)返回一个Future用于获得锁释放通知,并通过Semaphore.tryAcquire(ttl, TimeUnit.MILLISECONDS)在ttl时间内尝试获取一个信号量许可,获取到信号量许可后再次进行锁竞争,直至成功。

锁续命过程

使用锁续命而不是不限时的锁,是为了防止用户线程崩溃,导致锁一直未释放。所以每隔一段时间进行锁的续命,而不是设置永久锁,这样即便用户线程崩溃,也只是30s,无法访问。

  1. 锁续命需要判断用户是否设置过期时间,如果设置了过期时间,不会进行锁续命。

  2. 通过定时任务每30/3秒,找到当前线程对应的锁,如果存在重新设置过期时间为30秒。

锁释放过程

  1. 判断线程id(小key)是否存在,如果不存在,则返回null;如果存在,则可重入次数-1。

  2. 再判断可重入次数是否 > 0,如果 > 0,则不能释放锁,并重新设置锁过期时间。

  3. 如果 <= 0,则删除redis的大key,往(redisson_lock__channel + lockName)频道发送message,发送UNLOCK_MESSAGE。

Watch Dog(看门狗)

看门狗如何实现锁续期的?

第一次进入的时候,这里放进去的就是一个全新的ExpirationEntry类,并进行续约操作。续约操作其实就是创建一个延迟任务,默认每10s执行一次,延迟任务由HashedWheelTimer实现,核心是时间轮算法

如何修改看门狗续期时间?

配置lockWatchdogTimeout参数,可以调整看门狗续期频率和续期时间,默认lockWatchdogTimeout/3秒自动需求。

复制代码
Config config = new Config();
config.setLockWatchdogTimeout(60000); // 设置为 60 秒

如何设置看门狗不会续期?

指定leaseTime参数,这表示锁的有效期。在这个时间之后,如果没有主动释放,锁将自动失效并释放资源。

复制代码
RLocklock= redissonClient.getLock("myLock"); 
// 试图加锁,锁的过期时间设置为10秒钟 
lock.lock(10, TimeUnit.SECONDS);

情况下,Redisson的看门狗机制会停止续期?

  • 第一种情况:手工调用停止续期方法即cancelExpirationRenewal(),看门狗机制会停止续期。

  • 第二种情况:调用unlock()释放分布式锁后,看门狗机制也会停止续期。

  • 第三种情况:如果尝试续期的过程中,当前线程被中断,看门狗机制也会停止续期。

  • 第四种情况:应用程序宕机或者进程被kill掉,看门狗机制也会停止续期。


感谢您的阅读!如果文章中有任何问题或不足之处,欢迎及时指出,您的反馈将帮助我不断改进与完善。期待与您共同探讨技术,共同进步!

相关推荐
刘~浪地球3 小时前
Redis 从入门到精通(二):数据类型详解
数据库·redis·缓存
s1mple“”4 小时前
大厂Java面试实录:从Spring Boot到AI技术的电商场景深度解析
spring boot·redis·微服务·kafka·向量数据库·java面试·ai技术
会飞的大可5 小时前
Redis 竞品与替代方案选型可行性分析报告
数据库·redis·缓存
smachao6 小时前
Redis Desktop Manager(Redis可视化工具)安装及使用详细教程
redis·git·bootstrap
shark22222228 小时前
MySQL 与 Redis 的数据一致性问题
数据库·redis·mysql
MC皮蛋侠客8 小时前
C++中使用Redis指南:基于redis-plus-plus库
开发语言·c++·redis
難釋懷9 小时前
Redis缓存预热
redis·spring·缓存
zs宝来了10 小时前
Redis 哨兵机制:Sentinel 原理与高可用实现
redis·sentinel·高可用·源码解析·哨兵
会飞的大可10 小时前
Redis 故障排查与应急手册:从理论到实践
数据库·redis·缓存