1.redisson的所有指令都通过lua脚本来完成,保证了原子性

2.redisson设置一个key的默认过期时间为30s,如果某个客户端持有一个锁超过了30s怎么办?redisson中有一个watchdog的概念,翻译过来就是看门狗,它会在你获取锁之后,每隔10s帮你把key的超时时间设置为30s,这样的话,就算一直持有锁也不会出现key过期了其他线程获取到锁的问题了。

3.redisson的看门狗逻辑保证了没有死锁的发生,但是如果宕机了,看门狗也没了,此时就不会延长key的过期时间,到了时间就会自动过期,其他线程可以获取到锁。

借用下石杉老师的图可以更好的理解

Redisson的锁续期_看门狗


下面的测试代码的打印可以很直观的看出加锁解锁的过程,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);
}
}