浅谈Redisson底层源码

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6


Redisson源码分析

  • ​​一、加锁时使用lua表达式,执行添加key并设置过期时间​​
  • ​​二、加锁成功之后给锁添加对应的事件​​
  • ​​三、加锁完成,看门狗自动续命未处理完的线程​​
  • ​​四、线程加锁不成功,加锁自旋+阻塞​​
  • ​​五、释放锁之后触发事件,释放信号量​​
  • ​​六、补充RedissonMultiLock(RedissonRedLock)​​



Redisson底层实现锁的逻辑图



浅谈Redisson底层源码_信号量

Redisson分布式锁原理:

  • 可重入:利用hash结构记录线程id和重入次数
  • 可重试:利用信号量和PubSub功能实现等待、唤醒,获取锁失败的重试机制
  • 超时续约:利用watchDog,每隔一段时间(releaseTime/3),重置超时时间




一、加锁时使用lua表达式,执行添加key并设置过期时间

完成加锁操作,并添加锁的超时时间(默认为30S),类比理解setnx命令

获取锁成功,返回null,获取锁失败,返回key的剩余时间



浅谈Redisson底层源码_缓存_02



二、加锁成功之后给锁添加对应的事件

1、

加锁失败后,给锁注册对应的PUBSUB事件



浅谈Redisson底层源码_信号量_03


2、

最终方法对调用到subscribe方法,在该方法内部又会添加对应的监听事件



浅谈Redisson底层源码_信号量_04


3、

第五步,释放锁之后会触发该onMessage方法

当触发PUBSUB事件的时候,就会调用到这个onMessage方法。如果该PUBSUB事件是一个onlockMessage事件,则释放对应的信号量,即调用release方法



浅谈Redisson底层源码_缓存_05



三、加锁完成,看门狗自动续命未处理完的线程

1、

tryLockInnerAsync方法是一个异步任务,当加锁成功会会进入下面的operationComplete方法



浅谈Redisson底层源码_java_06


2、

在加锁成功,并且锁没有释放的基础上,使用lua脚本,对还没有释放的锁重新设置30S的后台看门狗续命时间。

续命成功之后会再次递归调用自己,完成下一次的续命逻辑。



浅谈Redisson底层源码_信号量_07



四、线程加锁不成功,加锁自旋+阻塞

与第一步相同的起点,如果第二把锁加锁不成功,返回的是第一把锁的超时时间。在while循环中,使用tryAcquire方法尝试加锁,直到加锁成功后,才会break(加锁成功返回null)

底下有一个getEntry().tryAcquire方法,该方法利用Semaphore信号量的阻塞机制。如果没有获取到对应的信号量,就阻塞,从而避免cpu空转,直到信号量释放之后(调用release方法,即第二步的onMessage方法中),才能继续往下走。



浅谈Redisson底层源码_redis_08



五、释放锁之后触发事件,释放信号量

释放锁之后会添加一个释放锁的事件(unlockMessage)



浅谈Redisson底层源码_缓存_09


该步骤就会触发第二步的onMessage方法,然后调用release方法释放对应的信号量。

释放完信号量,第三步中阻塞的线程就被唤醒,开启新一轮的while循环,再次尝试获取锁,如此往复。


此时让你再来梳理这个逻辑,应该就得心应手了

图片来源黑马,侵删



浅谈Redisson底层源码_java_10



六、补充RedissonMultiLock(RedissonRedLock)

1、

RedissonMultiLock加锁时是使用迭代器,对所有需要加锁的对象依次进行加锁操作



浅谈Redisson底层源码_加锁_11


2、

如果出现其中一个加锁不成功,那么就迭代上一个,让上一个再进行加锁,这就会出现上一个加锁不成功,然后递归向上到第一个锁,从头开始执行加锁操作



浅谈Redisson底层源码_java_12


3、

这里表示我们会重新设置所有锁对象的过期时间



浅谈Redisson底层源码_缓存_13


阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: redis