在Java中有许多保证线程安全的办法,比方synchorized,lock锁等等,这些在单机环境下都能发挥不错的效果,但是在分布式的环境下,这些机制就会失去大部分的效果。

在分布式环境下就需要引进分布式锁,完成分布式锁的办法有好多种,比方redis、zookeeper,或许经过数据库来完成,但是在分布式的状况下还需要考虑机器宕机的状况,假如某台机器上的线程获取到了这个锁,但此刻机器宕机了。那么就没办法去开释,就会造成死锁的状况。

为了防止这种状况,就需要给锁加上一个过期时刻,而过期时刻的设定又是一个令人十分头疼的问题。

在Redisson种有一个看门狗机制,它给出了一种过期时刻的很好的解决办法。下面就来研究一下它详细完成吧。

Redisson的加锁入口是tryLock(),此办法需供给获取锁的等待时刻,假如在规则时刻内未抢到锁,会回来false。

Redisson分布式锁底层实现原理

这儿能够看到tryLock()办法实际上是调用了下面这个办法,这儿给了一个leaseTime的默许值,至于为什么是-1,咱们接着往下看。

Redisson分布式锁底层实现原理

进来之后会发现,这个办法的中心便是履行一个tryAcquire办法,咱们点进去看一下。

Redisson分布式锁底层实现原理

tryAcquire办法实际会去履行tryAcquireAsync异步的去获取锁,然后再使用get获取成果,假如成果为null代表获取锁成功,这儿后边会讲。

Redisson分布式锁底层实现原理

然后进到tryAcquireAsync办法,在这儿判断了leaseTime是不是-1,假如咱们自己设定了过期时刻,那么就会以咱们设置的为准,并且不会去敞开主动续期。

假如是默许的-1,那么异步获取锁之后,后边还会去敞开一个主动续期的守时使命。

Redisson分布式锁底层实现原理

异步获取锁是经过tryLockInnerAsync这个办法完成的。第一个参数是30000,传入的是commandExecutor.getConnectionManager().getCfg().getLockWatchdogTimeout(),点进去能够看到

Redisson分布式锁底层实现原理

在这个办法里使用lua脚本的办法去履行了set操作

这段lua脚本的意思是:

锁不存在,加锁成功,设置hash数据结构锁: 锁名 -> 加锁线程:id -> 加锁次数(1)
锁存在且是本线程的锁 加锁次数添加:锁名 -> 加锁线程:id -> 加锁次数+1
锁存在且不是本线程的锁 加锁失利 回来锁剩余过期时刻

从这儿也能够表现出此锁的可重入,即某一线程获取到锁之后,那么这个线程再去获取该锁的话也能够成功

一起也能够假如回来为null那么阐明获取锁成功。

Redisson分布式锁底层实现原理

然后后边会判断假如成果为null,就会去履行scheduleExpirationRenewal(threadId)办法,进去看一下

Redisson分布式锁底层实现原理

由于咱们的Redission的分布式锁是可重入锁,所以这儿会首要判断一下是不是第一次加锁,假如不是第一次则加锁次数加 1 不会再敞开续期 因为第一次加锁时调用

假如是第一次加锁的话就回去调用renewExpiraton()去敞开主动续期。

Redisson分布式锁底层实现原理

addThreadId:重入次数+1

Redisson分布式锁底层实现原理

renewExpiraton()敞开主动续期这个办法里边创建了一个守时使命,主要逻辑是经过renewExpirationAsync(threadId)办法去履行续期逻辑,履行成功后还会经过下面if (res) {renewExpiration();}办法递归调用。

注意到这个线程履行的间隔是internalLockLeaseTime / 3,也便是30 / 3 = 10s

Redisson分布式锁底层实现原理

咱们能够看一下renewExpirationAsync办法里边的逻辑

此lua脚本的意思是:当时线程持有的锁是否还存在 存在的话重新设置锁的过期时刻(默许 30 秒)

Redisson分布式锁底层实现原理

至此加锁的逻辑就追完了。

下面咱们看一看开释锁的逻辑。其入口为:unlock办法,它会去调用unlockAsync办法。

Redisson分布式锁底层实现原理

unlockAsync里边掉了unlockInnerAsync办法去开释锁,

Redisson分布式锁底层实现原理

unlockInnerAsync办法点进去咱们能够看到它也是经过lua脚本的办法去开释锁。

若锁不存在 回来 若锁存在 加锁次数 -1 若加锁次数仍不等于 0 (可重入),重新设置锁的过期时刻,回来 若加锁次数减为 0,删除锁,同步发布开释锁事件,回来

Redisson分布式锁底层实现原理