Redisson分布式锁原理源码跟踪

Redisson

使用redis实现了分布式锁

分布式锁特性

互斥性

多个线程并发时,互相排斥,需要互斥则使用相同的key即可

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

getName为key名称,getLockName记录了线程

数据结构类似如下:

// redis key
{
  "线程id": 1
}

加锁成功脚本中都会返回nil,否则会返回剩余过期时间毫秒数

防死锁

防止加了锁,程序奔溃后没有释放锁的情况,导致其他线程永远无法成功加锁

通过给key添加过期时间来解决,但是如果过期时间到了,业务代码还没执行结束,这种情况redisson使用watch dog来解决,watch dog见下文

可重入

例如递归调用,如果当前线程加锁成功,当前线程递归调用该方法,应该可以成功加锁,而不是已经加了锁则报错加锁失败

在这里插入图片描述

lua脚本的第二个if中,判断了ARGV[2]即线程id存在情况下,对value进行次数增加1,所以可重入通过value记录了重入的次数

锁误删

即只能是加锁的人来解锁或者防死锁情况自动解锁

锁误删举例:

  1. 线程A进行加锁,并加锁成功,继续执行业务代码
  2. redis服务器宕机,并且没有持久化
  3. redis服务器恢复
  4. 线程B进行加锁,并加锁成功(此时Redis服务器中的锁事线程B加的)
  5. 线程A业务执行完成,执行锁释放,这事如果没有锁误删限制,那么线程A就会释放线程B加的锁

实现:

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

依旧通过线程id,作为hash的key的方式来防止误删

Watch Dog 看门狗

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

启动看门狗的代码如上图

使用commandExecutor.getConnectionManager().newTimeout的方式添加了一个延时任务

在这里插入图片描述

使用timer添加刚才定义的Task延时任务,看看timer是什么

在这里插入图片描述

HashedWheelTimer是netty提供的一个基于时间轮算法的延迟队列工具,用于延迟执行任务

时间轮算法

参考原文https://www.cnblogs.com/lihao007/p/10588072.html

在这里插入图片描述

HashedWheelTimer(
  					ThreadFactory threadFactory,
            long tickDuration, TimeUnit unit, int ticksPerWheel, boolean leakDetection,
            long maxPendingTimeouts)

threadFactory:线程工厂,用于创建工作线程,并且只会创建一个
tickDuration + unit:在每一个格子上的停留时间
ticksPerWheel:时间轮的格子数,每一个格子里都是一个Timeout任务队列bucket,双向链表结构
leakDetection:默认为true,开启泄漏检测
maxPendingTimeouts:最大挂起Timeouts任务数量

案例:

如图,一个轮分成8个bucket,每一个tick需要1秒,现在有一个延迟任务为延迟20秒后执行,则需要tick20次,1轮需要tick8次,则20/8 = 2轮,这个任务在添加到这个轮(wheel)中时,通过hash算法计算出应该放到哪一个目标bucket中并将计算出的2轮设置为该任务的剩余轮数,当指针每tick一次,落到这个bucket中时,会将bucket中的timeout(我们自己的延迟任务)的剩余轮数-1,当剩余轮数小于等于0的时候就执行该任务并从bucket中移除

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值