Redisson实现分布式锁原理、自动续期机制分析
admin
2024-03-16 00:47:41
0

前言:
在学习分布式锁之前,应该首先要分析一下使用分布式锁的必须要考虑的一些问题
1、互斥性:在并发的任意时刻,只能有一个线程拿到锁

2、防锁死:即使有一个线程在持有锁的期间崩溃而未能主动释放锁,还要有其他方式去释放锁从而保证其他进程能获取到锁

3、加锁和解锁的必须是同一个线程,解铃还须系铃人

4、锁续期:执行业务耗时的时间超过了锁的等待时间,必须进行锁续期

一、Redisson实现分布式锁

1、加锁原理
【1】Redisson 和 Redis 实现分布式锁是一致的,是不过 Redisson 是封装了 lua 脚本,保证获取、判断、加锁操作的原子性
【2】看一下加锁执行的 lua 脚本

if (redis.call('exists', KEYS[1]) == 0) then " +"redis.call('hincrby', KEYS[1], ARGV[2], 1); " +"redis.call('pexpire', KEYS[1], ARGV[1]); " +"return nil; " +"end; " +
"if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then " +"redis.call('hincrby', KEYS[1], ARGV[2], 1); " +"redis.call('pexpire', KEYS[1], ARGV[1]); " +"return nil; " +"end; " +
"return redis.call('pttl', KEYS[1]);"

【3】一个客户端要加锁,它首先会根据hash节点选择一台机器,这里注意仅仅只是选择一台机器,紧接着就会发送一段封装好的 lua 脚本到 redis 上,比如加锁的那个锁key就是"mylock",并且设置的时间是30秒,30秒后mylock锁就会被自动释放

2、锁互斥机制
【1】第一个线程加锁完成后,此时,如果客户端 2 来尝试加锁会如何呢?首先,第一个 if 判断会执行 exists myLock,发现 myLock 这个锁 key 已经存在了。接着第二个 if 判断,判断一下,myLock 锁 key 的 hash 数据结构中,是否包含客户端 2 的 ID,这里明显不包含客户端 2 的ID,因为那里包含的是客户端 1 的 ID。所以,客户端 2 会执行:

return redis.call('pttl', KEYS[1]);

返回的是一个数字,这个数字就是 myLock 这个锁 key 的剩余生存时间

3、锁阻塞机制
【1】当锁正在被其他线程占用的时候,等待获取锁的线程并不是通过一个 while(true) 死循环去获取锁,而是利用了 Redis 的发布订阅机制,通过 await 方法阻塞等待锁的进程,有效的解决 不断的申请锁浪费资源的问题

4、锁续期机制
【1】客户端 1 加锁的默认生存(等待)时间为30秒,如果超过了30秒,客户端 1 还想一直持有这把锁,怎么办?
【2】Redisson 提供了一个续期机制,只要客户端 1 一旦加锁成功,就会启动一个 Watch Dog (看门狗)
【3】Watch Dog 它是一个后台定时任务线程,会每隔10秒(internalLockLeaseTime / 3)检查一下(遍历 EXPIRATION_RENEWAL_MAP 里面线程 id 然后根据线程 id 去 Redis 中查,如果存在就会延长 key 的时间),如果客户端 1 还持有锁key,那么就会不断的延长锁key的生存时间,直至业务执行结束或者该线程主动释放锁

注意:

1、参数 leaseTime 必须是 -1 才会开启 Watch Dog 机制,也就是如果你想开启 Watch Dog 机制必须使用默认的加锁时间为 30s。如果你自定义释放时间,超过这个时间锁就会自定释放,并不会延长

2、这里有个问题,如果服务宕机了,Watch Dog 机制后台定时任务线程也就没有了,此时就不会延长 key 的过期时间,到了 30s 之后就会自动过期,其他线程就可以获取到锁

【4】续期说明、用法示例:

//拿锁失败会不停重试
//具有 Watch Dog 自动延期机制,默认续30s 每隔30/3=10 秒续到30s
lock.lock();//businessLock.tryTime() 秒之后停止重试加锁,返回false
//具有 Watch Dog 自动延期机制,默认续30s 每隔30/3=10 秒续到30s
boolean locked1 = lock.tryLock(businessLock.tryTime(), businessLock.timeUnit());//businessLock.tryTime() 秒之后停止重试加锁,返回false
//不具有 Watch Dog 自动延期机制
boolean locked2 = lock.tryLock(businessLock.tryTime(), businessLock.expire(), businessLock.timeUnit());//businessLock.tryTime() 秒之后停止重试加锁,返回false
//只有 leaseTime(默认-1) 等于 -1 时,才具有 Watch Dog 自动延期机制,默认续30s 每隔30/3=10 秒续到30s
boolean locked3 = lock.tryLock(businessLock.tryTime(), -1, businessLock.timeUnit());

注意:
【1】为保证业务执行耗时内锁不过期,最好使用默认的 30s 过期时间、或者自定义更长的过期时间
【2】拿到锁之后的等待时间,最好大于过期时间,避免后续线程拿锁失败

5、锁可重入机制 
【1】可重入锁就是在拿到锁之后、在内部还可以再次拿到锁,示例代码如下:

@Override
public void lock() {RLock lock = redissonSingle.getLock("myLock");try {lock.lock();// 执行业务doBusiness();lock.lock();} catch (Exception e) {e.printStackTrace();} finally {// 释放锁lock.unlock();lock.unlock();logger.info("任务执行完毕, 释放锁!");}
}

【2】如果加锁支持可重入锁,那么解锁呢?执行解锁就Ok了,拿几次锁解锁几次

lock.unlock()

二、总结

1、Redisson 通过 Watch Dog 机制很好的解决了锁的续期问题

2、Redisson 基于 Redis 性能很高,适合对性能要求高的场景

3、Redisson 实现分布式可重入锁,比原生的 SET mylock userId NX PX milliseconds + lua 实现的效果更好些,虽然基本原理都一样,但是它帮我们封装了内部的执行细节(官方封装更严谨)

4、在等待申请锁资源占用上也做了一些优化,减少了无效的锁申请,提升了资源的利用率

5、Redisson 的获取锁默认是非公平的(随机抢锁),可以使用 getFairLock() 获取公平锁对象(线程将以其请求的时间顺序获取锁),如下:

//公平锁,保证 Redisson 客户端线程将以其请求的顺序获得锁
RLock fairLock = redissonClient.getFairLock("fairLock");

相关内容

热门资讯

怎么解除订阅安卓系统,安卓系统... 你是不是也和我一样,手机里订阅了好多服务,结果现在想解除订阅,却一头雾水?别急,今天就来手把手教你如...
安卓系统停用怎么开启,轻松恢复... 亲爱的手机控们,你是否曾经遇到过安卓系统突然停用的情况,让你手忙脚乱,不知所措?别担心,今天就来教你...
安卓系统电池健康度,电池健康度... 你有没有发现,你的安卓手机最近是不是有点儿不给力了?电池续航能力大不如前,充电速度也慢了不少?别急,...
安卓系统按键怎么截图,安卓系统... 你是不是也和我一样,有时候想截个图分享给朋友,却发现安卓手机的截图功能有点神秘呢?别急,今天就来手把...
购票系统安卓源代码,架构设计与... 你有没有想过,那些我们每天离不开的购票系统,它们背后的秘密是什么呢?今天,就让我带你一探究竟,揭开购...
安卓手机系统后台测试,深度解析... 你有没有发现,你的安卓手机后台总是悄悄地忙碌着?别小看了这些后台程序,它们可是手机系统稳定运行的关键...
安卓系统重启的图标,解锁设备新... 手机突然重启,是不是心里有点慌?别急,今天就来和你聊聊安卓系统重启的图标,让你一眼就能认出它,再也不...
车载智慧屏安卓系统,智能出行新... 你有没有发现,现在的车载智慧屏越来越智能了?尤其是那些搭载了安卓系统的,简直就像是个移动的小电脑,不...
安卓系统连上网权限,解锁设备无... 你有没有发现,你的安卓手机里有些应用总是偷偷连上网?别小看这个小小的网络权限,它可是能影响你隐私、消...
安卓谷歌操作系统,探索安卓谷歌... 你知道吗?在智能手机的世界里,有一个操作系统可是无人不知、无人不晓,那就是安卓谷歌操作系统。它就像一...
安卓系统手写%怎样调出,具体实... 你有没有遇到过这种情况:在使用安卓手机的时候,突然想用手写输入法来记录一些灵感或者重要信息,可是怎么...
安卓手机重置 系统设置,轻松恢... 手机用久了是不是感觉卡顿得厉害?别急,今天就来教你怎么给安卓手机来个大变身——重置系统设置!想象你的...
win如何安装安卓系统,Win... 哇,你有没有想过,让你的Win系统也能玩转安卓应用?没错,就是那种在手机上轻松自如的安卓系统,现在也...
苹果qq和安卓系统,跨平台体验... 你有没有发现,现在手机市场上,苹果和安卓的较量可是越来越激烈了呢!咱们就来聊聊这个话题,看看苹果QQ...
显示最好的安卓系统,探索最新旗... 你有没有想过,为什么安卓系统那么受欢迎呢?它就像一个魔法盒子,里面装满了各种神奇的魔法。今天,就让我...
安卓app怎么降级系统,系统版... 你有没有发现,有时候安卓手机的系统更新后,新功能虽然炫酷,但老系统用起来更顺手呢?别急,今天就来教你...
雷军脱离安卓系统,引领科技变革... 你知道吗?最近科技圈可是炸开了锅,因为我们的雷军大大竟然宣布要脱离安卓系统,这可真是让人大跌眼镜啊!...
安卓系统自动开网络,安卓系统自... 你有没有发现,手机里的安卓系统有时候会自动开启网络连接,这可真是让人又爱又恨啊!有时候,你正专心致志...
安卓系统怎样控制后台,因为服务... 手机里的安卓系统是不是感觉越来越卡了?后台程序太多,不仅耗电还影响性能。别急,今天就来教你怎么巧妙地...
安卓系统打游戏推荐,一触即达! 你有没有发现,现在手机游戏越来越好玩了?不管是休闲小游戏还是大型MMORPG,都能在手机上畅玩。但是...