news 2026/11/6 6:34:32

看门狗(watch dog)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
看门狗(watch dog)

Redis 本身原生没有看门狗机制。

看门狗(Watch Dog)是 Redisson 实现分布式锁时自带的自动续期机制

不是 Redis 服务端命令。

Redis 原生分布式锁:SET key value NX EX ttl

  • 锁设置固定过期时间(默认30s);
  • 如果业务执行时间 > 锁过期时间 → 锁自动释放,并发安全失效。

看门狗解决什么问题

问题场景:

  1. 加锁,设置过期时间 30s
  2. 业务代码执行很慢(GC、IO 阻塞、慢查询),超过 30s 还没执行完、没释放锁
  3. Redis 自动把锁删掉
  4. 其他线程拿到同一把锁 →锁失效,并发问题

看门狗目标:

只要持有锁的业务线程还没释放锁,就持续延长锁的有效期,防止锁提前过期。

底层原理(Redisson)

不是全靠 Lua

Lua 只是【锁判断、续期、释放】这些原子操作的载体

看门狗整体整套逻辑,大量是 Java 客户端代码

底层:

使用:

  1. 引入 redisson 依赖,创建 RedissonClient 客户端。
  2. redissonClient.getLock(lockKey)获取 RLock 分布式锁(可重入)。
  3. lock()无参:开启看门狗,自动续期;带 leaseTime 参数:看门狗关闭,锁到期自动释放。
  4. tryLock():尝试抢锁;只传等待时间开看门狗,等待 + 持有时间都传则关闭看门狗。
  5. 业务放 try 里,finally 中先判断isHeldByCurrentThread(),再 unlock,防止别的线程解锁报错。

底层:加锁、续期、解锁靠 Lua 保证原子;看门狗是客户端 Netty 定时任务。

宕机后看门狗停止,锁到时间自动释放,不会死锁。

public class RedissonSimpleDemo { // 引入redisson依赖,创建RedissonClient客户端 public static RedissonClient getRedissonClient() { Config config = new Config(); config.useSingleServer() .setAddress("redis://127.0.0.1:6379"); return Redisson.create(config); } public static void main(String[] args) throws InterruptedException { RedissonClient redissonClient = getRedissonClient(); String lockKey = "business:lock"; // redissonClient.getLock(lockKey) 获取RLock分布式锁(可重入) //RLock在Redis是Hash结构 RLock lock = redissonClient.getLock(lockKey); try { // lock()无参:开启看门狗,自动续期 lock.lock(); System.out.println("执行业务"); TimeUnit.SECONDS.sleep(35); } finally { // finally中先判断isHeldByCurrentThread(),再unlock,防止别的线程解锁报错 if (lock.isHeldByCurrentThread()) { lock.unlock(); } } // tryLock():尝试抢锁;只传等待时间开看门狗 boolean tryLockResult = false; RLock lock2 = redissonClient.getLock(lockKey); try { tryLockResult = lock2.tryLock(10, TimeUnit.SECONDS); if (tryLockResult) { System.out.println("tryLock执行业务"); TimeUnit.SECONDS.sleep(25); } } finally { if (tryLockResult && lock2.isHeldByCurrentThread()) { lock2.unlock(); } } // tryLock():等待+持有时间都传则关闭看门狗 boolean tryLockResult2 = false; RLock lock3 = redissonClient.getLock(lockKey); try { tryLockResult2 = lock3.tryLock(10,15, TimeUnit.SECONDS); if (tryLockResult2) { System.out.println("指定leaseTime执行业务,看门狗关闭"); TimeUnit.SECONDS.sleep(20); } } finally { if (tryLockResult2 && lock3.isHeldByCurrentThread()) { lock3.unlock(); } } redissonClient.shutdown(); } }

tryLock()

尝试抢锁,不会一直阻塞死等,抢到返回 true(锁重入了,field计数+1),否则返回 false

有两种常用重载:

  1. tryLock(waitTime, TimeUnit):最多等待 waitTime 时间抢锁,抢到就持有,开启看门狗
  2. tryLock(waitTime,leaseTime, TimeUnit):最多等 waitTime;抢到之后锁最多持有 leaseTime,关闭看门狗,不会自动续期

waitTime:愿意花多久等锁;leaseTime:锁的有效期

误区:锁重入关闭看门狗指的是本次加锁不开启看门狗还是说锁重入之前那次加的锁的看门狗也关闭?

重入不会把之前已经启动的看门狗关掉!只是:这次重入这一次,不会再额外新建一个看门狗。

unlock()

释放当前线程持有的这把分布式锁。

  • 底层走 Lua 脚本:hash 重入计数减一,计数到 0 就删除锁 key,同时停止看门狗定时任务
  • ⚠️ 只能自己解自己的锁;别的线程去 unlock 会报错,所以代码里要配合isHeldByCurrentThread()判断

复习:

  1. try:放需要执行的业务代码(加锁后的逻辑),正常跑、或者抛出异常,都会往下走
  2. finally:无论 try 里面正常结束、还是抛异常、还是 return,finally 代码几乎一定会执行

Redisson 的锁结构不是简单 string,是hash 结构:

  • key:锁名称
  • field:当前线程唯一 ID
  • value:重入计数(支持可重入锁)

好处:可以精准判断:这把锁是不是当前这个线程持有的,防止续别人的锁

豆包讲全流程:

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/11/6 6:25:03

明日方舟日常自动化:MAA 助手从安装到跑通的完整指南

明日方舟日常自动化:MAA 助手从安装到跑通的完整指南 【免费下载链接】MaaAssistantArknights 《明日方舟》小助手,全日常一键长草!| A one-click tool for the daily tasks of Arknights, supporting all clients. 项目地址: https://gitc…

作者头像 李华
网站建设 2026/11/6 6:17:47

Mars 踩坑实录:Android 2.1 缺 Object.keys 时的两行 for-in 替代写法

Mars 踩坑实录:Android 2.1 缺 Object.keys 时的两行 for-in 替代写法 【免费下载链接】Mars 腾讯移动 Web 前端知识库 项目地址: https://gitcode.com/gh_mirrors/mar/Mars 维护低版本 Android 页面的人,大概率撞见过这样一个报错:An…

作者头像 李华
网站建设 2026/11/6 6:15:07

GSYVideoPlayer:Android 视频播放从接入到切换内核的实践笔记

GSYVideoPlayer:Android 视频播放从接入到切换内核的实践笔记 【免费下载链接】GSYVideoPlayer Video players (IJKplayer, ExoPlayer, MediaPlayer), HTTPS, 16k page size, danmaku (bullet chat) support, external subtitles, support for filters, watermarks,…

作者头像 李华
网站建设 2026/11/6 6:13:11

ARMv9 SCP电源管理服务深度解析:从架构原理到调优实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/11/6 6:10:38

OpenHarmony I2C驱动实战:从物理层到HDF排障全链路解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华