一、什么是缓存续命
Redis 分布式锁过期了,但是业务逻辑还没处理完怎么办?
守护线程续命,额外起一个线程,定期检查线程是否还持有锁,如果有则延长过期时间。Redisson 里面就实现了这个方案,使用 “看门狗” 定期检查(每1/3的锁时间检查1次),如果线程还持有锁,则刷新过期时间。
在获取锁成功后,给锁加一个 watchdog,watchdog 会起一个定时任务,在锁没有被释放且快要过期的时候会续期。
注意:
- lock() 方法加锁成功 默认过期时间 30 秒, 并且支持 "看门狗" 续时功能。
- 如果设置leaseTime,则不会开启“看门狗”。
二、源码分析
1、源码1
通过redisson新建出来的锁key,默认是30秒。
2、源码2
3、源码3
这里面初始化了一个定时器,dely 的时间是 internalLockLeaseTime/3。在 Redisson 中,internalLockLeaseTime 是 30s,也就是每隔 10s 续期一次,每次 30s。
watch dog自动延期机制
客户端A加锁成功,就会启动一个watch dog看门狗,他是一个后台线程,会每隔10秒检查一下,如果客户端A还持有锁key,那么就会不断的延长锁key的生存时间,默认每次续命又从30秒新开始。
4、源码4
底层的lua脚本
KEYS[1]代表的是你加锁的那个key | RLock redissonLock = redisson.getLock("lockzzyy");这里你自己设置了加锁的那个锁key |
ARGV[2]代表的是加锁的客户端的ID | |
ARGV[1]就是锁key的默认生存时间 | 默认30秒 |
如何加锁 | 你要加锁的那个锁key不存在的话,你就进行加锁 hincrby 7bcf6a9f-e7f7-49b0-9727-141df3b88038:117 1 接着会执行 pexpire lockzzyy 30000 |
流程解释
(1)通过exists判断,如果锁不存在,则设置值和过期时间,加锁成功。
(2)通过hexists判断,如果锁已存在,并且锁的是当前线程,则证明是重入锁,加锁成功。
(3)如果锁已存在,但锁的不是当前线程,则证明有其他线程持有锁。返回当前锁的过期时间(代表了lockzzyy这个锁key的剩余生存时间),加锁失败。
加锁成功后,在redis的内存数据中,就有一条hash结构的数据。
Key为锁的名称;field为随机字符串+线程ID;值为1。见下
如果同一线程多次调用lock方法,值递增1。——可重入锁