发布时间:2026/7/24 20:14:29
Redisson的看门狗机制 ​​​​​​​Redisson的看门狗机制原理Redisson看门狗机制相关背景Redis分布式锁的看门狗机制是Redisson为解决‌业务执行时间超过锁过期时间、锁提前释放引发并发安全问题‌设计的自动续期机制。下图展示了Redisson看门狗机制的核心运行流程flowchart TD A[业务线程调用 lock() 或 tryLock()] -- B{是否指定 leaseTime?} B -- 是 -- C[手动指定过期时间 看门狗不生效] B -- 否 -- D[获取锁成功 设置初始TTL30秒] D -- E[启动看门狗定时任务] E -- F{定时检查每10秒} F -- 锁仍被当前线程持有 -- G[执行Lua脚本续期 重置TTL为30秒] G -- F F -- 锁已释放或线程不持有 -- H[停止续期] C -- I[业务执行完成] D -- I I -- J[调用 unlock() 释放锁] J -- K[看门狗任务终止] L[客户端进程宕机] -- M[看门狗任务终止] M -- N[锁在最后一次续期后30秒自动过期]流程说明获取锁业务线程调用lock()或tryLock()且不指定leaseTime时Redisson会为锁设置默认30秒的初始TTL。启动定时任务后台立即启动基于Netty时间轮的看门狗定时任务。定期检查与续期每10秒TTL的1/3检查一次锁状态。若锁仍被当前线程持有则通过Lua脚本原子性地将锁的TTL重置为30秒。循环续期只要业务未完成且未调用unlock()续期动作就会持续循环防止锁过期。停止条件业务正常完成调用unlock()释放锁看门狗任务立即终止。客户端进程宕机看门狗任务随之终止锁在最后一次续期后30秒自动过期避免永久死锁。Redisson看门狗机制相关背景Redis分布式锁的看门狗机制是Redisson为解决‌业务执行时间超过锁过期时间、锁提前释放引发并发安全问题‌设计的自动续期机制。1. 核心生效前提只有调用tryLock()时未手动指定锁的租约时间传入leaseTime-1看门狗才会自动启动若手动设置了过期时间Redisson会认为用户自行管控锁生命周期不会触发看门狗逻辑。2. 基础运行原理锁初始化时默认给锁设置‌30秒‌的初始TTL该默认值可通过配置修改。后台启动基于Netty时间轮的轻量定时任务每10秒默认TTL的1/3检查一次锁状态若锁仍被当前线程持有就通过Lua脚本将锁的过期时间重置为30秒。只要业务线程未执行完、未调用unlock()释放锁续期动作就会循环持续避免锁提前过期。3. 停止续期的触发条件业务正常执行完成主动调用unlock()删除锁看门狗任务直接终止。客户端进程宕机看门狗定时任务随之终止锁会在最后一次续期后的30秒自动过期释放不会出现永久死锁。4. 底层实现细节看门狗的续期逻辑通过Lua脚本原子执行先校验锁是否仍被当前线程持有确认后再重置过期时间避免误续其他线程持有的锁保证续期操作的线程安全。Spring Boot 整合 Redis 实现看门狗机制完整示例1. 环境准备Maven 依赖dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-redis/artifactId /dependency dependency groupIdorg.redisson/groupId artifactIdredisson-spring-boot-starter/artifactId version3.27.0/version /dependencyapplication.yml 配置spring: redis: host: localhost port: 6379 # 密码如有 # password: yourpassword redisson: 单节点配置 single-server-config: address: redis://${spring.redis.host}:${spring.redis.port} # 连接池大小 connection-pool-size: 64 # 连接最小空闲数 connection-minimum-idle-size: 24 # 连接超时时间毫秒 connect-timeout: 10000 # 命令等待超时时间毫秒 timeout: 30002. Redisson 配置类import org.redisson.Redisson; import org.redisson.api.RedissonClient; import org.redisson.config.Config; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; Configuration public class RedissonConfig { Value(${spring.redis.host}) private String redisHost; Value(${spring.redis.port}) private int redisPort; Bean public RedissonClient redissonClient() { Config config new Config(); // 使用单节点模式 config.useSingleServer() .setAddress(redis:// redisHost : redisPort) // 看门狗默认锁超时时间毫秒默认 30000 .setLockWatchdogTimeout(30000) // 连接池配置 .setConnectionPoolSize(64) .setConnectionMinimumIdleSize(24) .setConnectTimeout(10000) .setTimeout(3000); return Redisson.create(config); } }3. 分布式锁服务类import org.redisson.api.RLock; import org.redisson.api.RedissonClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.concurrent.TimeUnit; Service public class DistributedLockService { Autowired private RedissonClient redissonClient; /** 获取锁启用看门狗自动续期 param lockKey 锁的key return 锁对象 */ public RLock lockWithWatchdog(String lockKey) { RLock lock redissonClient.getLock(lockKey); // 不传 leaseTime 或传 -1看门狗自动生效 lock.lock(); return lock; } /** 尝试获取锁启用看门狗自动续期 param lockKey 锁的key param waitTime 等待时间秒 return 是否获取成功 */ public boolean tryLockWithWatchdog(String lockKey, long waitTime) throws InterruptedException { RLock lock redissonClient.getLock(lockKey); // leaseTime 传 -1看门狗自动生效 return lock.tryLock(waitTime, -1, TimeUnit.SECONDS); } /** 获取锁手动指定过期时间不启用看门狗 param lockKey 锁的key param leaseTime 锁的持有时间秒到期自动释放 return 锁对象 */ public RLock lockWithLeaseTime(String lockKey, long leaseTime) { RLock lock redissonClient.getLock(lockKey); // 指定 leaseTime看门狗不生效 lock.lock(leaseTime, TimeUnit.SECONDS); return lock; } /** 释放锁 param lock 锁对象 */ public void unlock(RLock lock) { if (lock ! null lock.isLocked() lock.isHeldByCurrentThread()) { lock.unlock(); } } }4. 业务使用示例import org.redisson.api.RLock; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.concurrent.TimeUnit; Service public class OrderService { Autowired private DistributedLockService lockService; private static final String ORDER_LOCK_PREFIX order:lock:; /** 创建订单使用看门狗保证长任务锁安全 */ public void createOrderWithWatchdog(Long orderId) { String lockKey ORDER_LOCK_PREFIX orderId; RLock lock null; try { // 获取锁看门狗自动续期 lock lockService.lockWithWatchdog(lockKey); // 或者使用 tryLock同样启用看门狗 // boolean locked lockService.tryLockWithWatchdog(lockKey, 5); // if (!locked) { // throw new RuntimeException(获取锁失败); // } // 模拟耗时业务操作可能超过30秒 TimeUnit.SECONDS.sleep(40); System.out.println(订单创建成功订单ID: orderId); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new RuntimeException(订单创建被中断, e); } finally { // 释放锁看门狗任务终止 lockService.unlock(lock); } } /** 快速操作手动指定过期时间不启用看门狗 */ public void quickOperation(Long resourceId) { String lockKey resource:lock: resourceId; RLock lock null; try { // 获取锁10秒后自动过期 lock lockService.lockWithLeaseTime(lockKey, 10); // 快速业务操作 TimeUnit.SECONDS.sleep(5); System.out.println(快速操作完成资源ID: resourceId); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new RuntimeException(操作被中断, e); } finally { // 锁会在10秒后自动释放也可手动释放 lockService.unlock(lock); } } }5. 测试控制器import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; RestController public class LockTestController { Autowired private OrderService orderService; /** 测试看门狗机制 */ GetMapping(/order/create/{orderId}) public String createOrder(PathVariable Long orderId) { try { orderService.createOrderWithWatchdog(orderId); return 订单创建成功订单ID: orderId; } catch (Exception e) { return 订单创建失败: e.getMessage(); } } /** 测试手动过期锁 */ GetMapping(/resource/operate/{resourceId}) public String operateResource(PathVariable Long resourceId) { try { orderService.quickOperation(resourceId); return 资源操作成功资源ID: resourceId; } catch (Exception e) { return 资源操作失败: e.getMessage(); } } }6. 关键配置说明lockWatchdogTimeout看门狗检查间隔默认30000毫秒30秒。看门狗会在锁过期前1/3时间10秒进行检查和续期。leaseTime参数调用lock(leaseTime, unit)或tryLock(waitTime, leaseTime, unit)时如果leaseTime 0看门狗不生效如果leaseTime -1或不传看门狗生效。锁释放业务完成后必须调用unlock()否则看门狗会持续续期直到进程终止。7. 注意事项看门狗机制只在使用Redisson的RLock接口且未指定leaseTime时生效。确保Redis连接稳定网络波动可能导致续期失败锁提前释放。生产环境建议配置Redis哨兵或集群模式提高可用性。监控锁的持有时间避免业务逻辑异常导致锁长期占用。

相关新闻

2026/7/24 20:14:29

不同系统下设置静态IP

虽然所有 Linux 系统在底层的内核操作是相同的(临时配置都可以用 ip 或 ifconfig),但让静态 IP 永久生效的配置文件格式、路径以及后台网络管理服务,在不同操作系统中截然不同。各大常见系统设置静态 IP 的机制对比与操作示例说明…

2026/7/24 21:39:35

AI副业合法变现路径图(2024最新监管白皮书实操版)

更多请点击: https://intelliparadigm.com 第一章:AI副业合法变现的底层合规逻辑 AI副业的可持续性不取决于模型有多强大,而在于其商业行为是否嵌入法定权利义务框架之中。合法变现的核心,是将技术输出转化为受法律承认的“可交易…

2026/7/24 21:39:35

高并发内存池 - central cache 结构设计

高并发内存池 - central cache 结构设计 项目 gitee 链接: 高并发内存池项目 项目 github 链接: 高并发内存池项目 central cache 也是一个哈希桶结构,并且映射关系与 thread cache 保持一致,但是链接部分不再是自由链表&#x…

2026/7/24 21:39:35

Druid相关知识梳理

文章目录 Druid 是什么? 核心功能(必背) 为什么要用 Druid?(优点) 一句话速记 总结 具体连接举例 1. 导入依赖 2. 核心区别 3. 代码实操 配置参数 创建Druid数据源(连接池) 4. 一句话总结 5. 多库延伸 为啥不用原生JDBC,非要用Druid 1. 原生JDBC致命缺点 2. Druid连接…

2026/7/24 21:39:35

deepseek 怎么导出 pdf?借助 AI 导出鸭,轻松解决各类导出格式困扰

DeepSeek导出PDF的技术纵深:从格式崩塌到结构化数据流转的工程进化 一、痛点:当“导出PDF”成为知识工程的最后一公里诅咒 在实际的AI工程化落地中,一个看似简单的功能——将AI生成内容导出为PDF,正在成为结构化工单、技术文档、科…

2026/7/24 21:39:35

HSTracker:3大功能让你的炉石传说胜率飙升50%

HSTracker:3大功能让你的炉石传说胜率飙升50% 【免费下载链接】HSTracker A deck tracker and deck manager for Hearthstone on macOS 项目地址: https://gitcode.com/gh_mirrors/hs/HSTracker 还在为记不住对手的卡牌而烦恼?每次抽牌都像在赌博…

2026/7/24 21:34:35

呆啵宠物:让二次元角色住进桌面的终极开源桌宠框架

呆啵宠物:让二次元角色住进桌面的终极开源桌宠框架 【免费下载链接】DyberPet Desktop Cyber Pet Framework based on PySide6 项目地址: https://gitcode.com/GitHub_Trending/dy/DyberPet 呆啵宠物DyberPet是一款基于PySide6开发的桌面宠物开源框架&#x…

2026/7/23 12:54:51

Unity与Python本地通信:基于Flask的跨语言数据交换实战

1. 项目概述:为什么我们需要一个本地通信服务器?在游戏开发、数字孪生、仿真训练等众多领域,Unity作为强大的实时3D内容创作平台,其核心逻辑通常由C#驱动。然而,当我们需要进行复杂的数据分析、机器学习推理、科学计算…

2026/7/24 0:03:10

不同品牌斜齿行星减速机如何替换?以PX与PAG系列为例

不同品牌斜齿行星减速机如何替换?以 PX 与 PAG 系列为例 一、系列对应不等于型号直接互换 PX 与 PAG 都属于斜齿、方法兰、输出轴式精密行星减速机,结构形式和应用方向具有对应关系。 原设备使用PX系列时,可以优先从PAG系列中寻找替换型号。但…

2026/7/24 0:03:10

jdk8 把list 扁平化成String 多个以逗号分隔

在 JDK 8 中&#xff0c;将 List 扁平化为以逗号分隔的 String&#xff0c;有几种非常简洁且高效的方法。&#x1f680; 推荐方案&#xff1a;使用 Collectors.joining()这是最标准的 Java 8 写法&#xff0c;适用于 List<String>。javaimport java.util.stream.Collecto…

2026/7/24 0:03:10

java 两个 long id 怎么合并成一个long id 并且不重复

“把两个 Long ID 合并成一个唯一的 Long ID&#xff0c;且保证不重复”这个需求&#xff0c;在 Java 里直接做数学上的“完美合并”是不可能的。因为两个 Long&#xff08;各 64 位&#xff09;要合并成一个 Long&#xff08;64 位&#xff09;&#xff0c;在信息论上是有损压…

2026/7/23 23:42:43

3个高效策略:快速掌握Axure中文界面配置

3个高效策略&#xff1a;快速掌握Axure中文界面配置 【免费下载链接】axure-cn Chinese language file for Axure RP. Axure RP 简体中文语言包。支持 Axure 11、10、9。不定期更新。 项目地址: https://gitcode.com/gh_mirrors/ax/axure-cn 还在为Axure RP的英文界面感…