Redisson的锁续期
原创
©著作权归作者所有:来自51CTO博客作者某科学的南条的原创作品,请联系作者获取转载授权,否则将追究法律责任
1.redisson的所有指令都通过lua脚本来完成,保证了原子性
2.redisson设置一个key的默认过期时间为30s,如果某个客户端持有一个锁超过了30s怎么办?redisson中有一个watchdog的概念,翻译过来就是看门狗,它会在你获取锁之后,每隔10s帮你把key的超时时间设置为30s,这样的话,就算一直持有锁也不会出现key过期了其他线程获取到锁的问题了。
3.redisson的看门狗逻辑保证了没有死锁的发生,但是如果宕机了,看门狗也没了,此时就不会延长key的过期时间,到了时间就会自动过期,其他线程可以获取到锁。
借用下石杉老师的图可以更好的理解
![在这里插入图片描述 Redisson的锁续期_看门狗](https://s2.51cto.com/images/blog/202302/20163418_63f3308a1b26099637.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184)
下面的测试代码的打印可以很直观的看出加锁解锁的过程,redisson的这个key的过期时间是设置的20s,但是执行的业务流程需要41秒,在RedisDesktopManager中看到redisson的过期时间每到14秒左右就重置为20秒了,大概是三分之一的过期时间,这就是看门狗在帮助我们为锁续期。
package com.qiangqiang.config;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;
/**
* \* Created with IntelliJ IDEA.
* \* @author: xiyue
* \* Date: 2021/1/29
* \* Time: 15:46
* \* To change this template use File | Settings | File Templates.
* \* Description:
* \
*/
public class RedissonTest {
public static final String REDISSON_LOCK = "redisson";
public static void main(String[] args) throws InterruptedException{
RedissonClient redissonClient = redissonClient();
RLock lock = redissonClient.getLock(REDISSON_LOCK);
lock.lock();
System.out.println(LocalDateTime.now() + "=> add my-test-lock");
newAThread(redissonClient);
TimeUnit.SECONDS.sleep(41);
lock.unlock();
System.out.println(LocalDateTime.now() + "=> delete my-test-lock");
}
public static void newAThread(RedissonClient redissonClient){
new Thread(() ->{
while (true){
try {
RLock anotherLock = redissonClient.getLock(REDISSON_LOCK);
boolean lockSuccess = anotherLock.tryLock(1, -1, TimeUnit.SECONDS);
if(!lockSuccess){
System.out.println(LocalDateTime.now() + "-> try lock failed");
}else{
System.out.println(LocalDateTime.now() + "-> try lock success");
anotherLock.unlock();
System.out.println(LocalDateTime.now() + "-> delete lock success");
return;
}
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
private static RedissonClient redissonClient(){
Config config = new Config();
config.useSingleServer().setAddress("redis://192.168.214.129:6379");
config.setLockWatchdogTimeout(20*1000);
return Redisson.create(config);
}
}