Redis分布式锁比较正确的姿势是采用redisson
这个客户端工具。
可重入锁(Reentrant Lock)
基于Redis的Redisson分布式可重入锁RLock。
public class DemoMain {
public static void main(String[] args) throws Exception {
Config config = new Config();
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
RedissonClient redisson = Redisson.create(config);
RLock lock = redisson.getLock("anyLock");
lock.lock();
...
//lock.unlock();
}
}
问题分析 Redisson节点宕机&锁续期
锁超时-节点宕机
如果负责存储分布式的Redisson节点宕机,而且这个锁正好处于上锁的状态时,那么就会出现我们所谓的死锁的状态。但是为了避免这种情况的发生,Redisson内部已经提供了一种机制。可通过Redisson通过加锁的方式提供了leaseTime的参数来指定加锁的时间,超过这个时间这个锁就自动解开了。
锁续期-节点宕机
Redisson内部已经提供了一种机制,LockWatchDog(看门狗) 即提供了一个监控锁的看门狗,它的作用是在Redisson实例被关闭前,不断的延长锁的有效期。默认情况下,看门狗检查锁超时时间的间隔为30秒,这个时间可通过Config.lockWatchDogTimeout来进行指定。
Redisson.create(config);
通过源码:internalLockLeaseTime
和 lockWatchdogTimeout
这两个参数是相等的.
lockWatchdogTimeout
默认值如下
public class Config {
private long lockWatchdogTimeout = 30 * 1000;
public long getLockWatchdogTimeout() {
return lockWatchdogTimeout;
}
//...
}
internalLockLeaseTime
:分布式锁的超时时间默认是30秒.
看门狗,多久来延长一次有效期呢?
即:获取锁成功就会开启一个定时任务,也就是watchdog
,定时任务会定期检查去续期renewExpirationAsync(threadId)
.
这里定时用的是netty-common
包中的HashedWheelTimer
,该定时调度每次调用的时间差是internalLockLeaseTime / 3
.也就10秒.
总结
默认情况下,加锁的时间是30秒.如果加锁的业务没有执行完,那么到 30-10 = 20秒的时候,就会进行一次续期,把锁重置成30秒.那这个时候可能又有同学问了,那业务的机器万一宕机了呢?宕机了定时任务跑不了,就续不了期,那自然30秒之后锁就解开了.
注:内容总结于肥朝微信公众号,在此只是当做学习笔记-非原创