首页 > 数据库 >浅谈Redisson底层源码

浅谈Redisson底层源码

时间:2023-01-18 22:34:18浏览次数:40  
标签:释放 加锁 浅谈 成功 信号量 源码 线程 Redisson 方法


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底层源码_java_03


2、

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



浅谈Redisson底层源码_缓存_04


3、

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

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



浅谈Redisson底层源码_加锁_05



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

1、

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



浅谈Redisson底层源码_加锁_06


2、

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

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



浅谈Redisson底层源码_java_07



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

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

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



浅谈Redisson底层源码_加锁_08



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

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



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


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

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


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

图片来源黑马,侵删



浅谈Redisson底层源码_redis_10



六、补充RedissonMultiLock(RedissonRedLock)

1、

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



浅谈Redisson底层源码_加锁_11


2、

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



浅谈Redisson底层源码_缓存_12


3、

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



浅谈Redisson底层源码_java_13


标签:释放,加锁,浅谈,成功,信号量,源码,线程,Redisson,方法
From: https://blog.51cto.com/u_15942107/6019537

相关文章

  • drf快速使用 CBV源码分析 drf之APIView分析 drf之Request对象分析
     目录序列化和反序列化drf介绍和安装使用原生django写接口djangoDRF安装drf快速使用模型序列化类视图路由datagrip使用postman测试接口CBV源码分......
  • 浅谈三种使用Redis实现MQ的方式
    文章目录​​一、消息队列​​​​二、基于List的消息队列​​​​三、基于PubSub的消息队列​​​​四、基于Stream的消息队列​​​​1、基本命令​​​​2、简单使用​​......
  • 浅谈如何使用Redis实现分布式锁
    文章目录​​一、基础版(含自动释放锁)​​​​二、改良版(含过期时间)​​​​三、进阶版(含唯一性验证)​​​​四、单节点版(含Redisson)​​​​五、多节点版(含RedLock)​​写在......
  • 浅谈Redis底层数据结构(sdshdr-redisObject)
    最近看了点Redis底层的源码分析,特作此记录前提共识:Redis是一个默认为16个数据库的key-value内存数据库Redis底层是由C语言实现文章目录​​C语言源码流程​​​​1、server.......
  • 浅谈Zookeeper集群选举Leader节点源码
    写在前面:zookeeper源码比较复杂,本文讲解的重点为各个zookeeper服务节点之间的state选举。至于各个节点之间的数据同步,不在文本的侧重讲解范围内。在没有对zookeeper组件有一......
  • 浅谈Redis基本数据类型底层编码(含C源码)
    文章目录​​一、String​​​​1、int​​​​2、embstr​​​​3、raw​​​​4、bitmap​​​​5、hyperloglog​​​​二、List​​​​1、ziplist​​​​2、quicklist......
  • 浅谈如何设计MySQL索引
    文章目录​​一、索引的代价​​​​二、如何设计索引​​​​1、索引列的类型尽量小​​​​2、索引的选择离散性高的​​​​3、只为用于搜索、排序或分组的列创建索引​......
  • STM32 PLC底层源码 FX2N源码 断电保持/Keil源码
    STM32PLC底层源码FX2N源码断电保持/Keil源码三菱指令编码注释较多,适合初学者,发编译环境:KeilMDK4.7以上的版本,CPU需要:STM32F103--RAM内存不小64K,Flash程序空间不小于256......
  • JS 前端大文件上传源码
    ​对于大文件的处理,无论是用户端还是服务端,如果一次性进行读取发送、接收都是不可取,很容易导致内存问题。所以对于大文件上传,采用切块分段上传,从上传的效率来看,利用多线程......
  • JDK 1.8 TreeMap源码分析
    /**   *TreeMap特点:   * 底层:二叉红黑树key输入无序,升序排列,null不可以   * 1.2    */publicclassTreeMap<K,V>   extendsAbstractMap<K......