一、什么是Redisson

1.Redisson是架设在Redis基础上的一个Java驻内存数据网格(In-Memory Data Grid),它实现了分布式和可扩展的Java数据结构。

2.它不仅提供了一系列的分布式的Java常用对象,还实现了可重入锁(Reentrant Lock)、公平锁(Fair Lock)、联锁(MultiLock)、红锁(RedLock)、 读写锁(ReadWriteLock)等,还提供了许多分布式服务。

二、Redisson的宗旨

促进使用者对redis的关注分离,从而让使用者能够将精力更集中地放在处理业务逻辑上。

三、分布式锁的实现

Redis要实现分布式锁,必须满足以下条件

  • 互斥性:在任意时刻,只有一个客户端能持有锁。
  • 无死锁:客户端在持有锁期间,如果出现宕机,不能释放锁,导致后续其他客户端无法获取锁,必须保证宕机情况下,也能释放锁。
  • 容错性:只要大部分的redis节点正常运行,客户端就可以加解锁。

1、分布锁的演变
以前实现分布式锁是基于jedis+Lua脚本,但jedis是线程不安全的,常常通过JedisPool连接池去管理实例,在多线程情况下让每个线程有自己独立的jedis实例,但是随着现代系统的多核和异步,为了不断提高的吞吐量,异步非阻塞线程模型大行其道,Redisson底层是从用Netty框架,出身既是贵族,很多大厂都开始用Redisson实现分布式锁。

2、采用Resisson实现分布式锁

  • 配置文件pom.xml

redis与Hadoop哪个好 redis和redisson_客户端

  • application.yaml

redis与Hadoop哪个好 redis和redisson_分布式锁_02

  • 配置类config(只做单点连接)

redis与Hadoop哪个好 redis和redisson_分布式锁_03

  • 实现类

redis与Hadoop哪个好 redis和redisson_redis_04

  • 步骤1:源码分析

redis与Hadoop哪个好 redis和redisson_redis_05

  • 步骤2:源码分析

RedissonLock实现Rlock接口,重写tryLock方法

redis与Hadoop哪个好 redis和redisson_redis与Hadoop哪个好_06


沿着tryLockAsync()往下走,到最底层是Lua脚本

redis与Hadoop哪个好 redis和redisson_redis与Hadoop哪个好_07


eval命令执行Lua代码完成加锁操作。KEYS[1]为锁在redis中的key,key对应value为map结构,ARGV[1]为锁超时时间,ARGV[2]为锁value中的key。ARGV[2]由UUID+threadId组成,用来标记锁被谁持有。

流程:

1、第一个if判断key是否存在,如果不存在,就获取锁,赋值,设置过期时间。

2、第二个if判断key是否存在,如果存在,对比ARGV[2]判断请求的标记值和锁的标记值是否一样,如果一样,则说明已经获取了锁,这时候hincrby锁重入+1,(redis.call(‘hincrby’, KEYS[1], ARGV[2], 1);记录同一线程持有锁之后累计加锁次数实现锁重入)。

3、重置锁的过期时间 。

4、加锁失败,返回锁的过期时间。

----------------------------------------------------------xx--------------------------------------------------------

对于获取不到的锁的线程,它会继续请求获取锁,直接到锁被释放

redis与Hadoop哪个好 redis和redisson_redis与Hadoop哪个好_08


A

表示以共享方式获取锁,获取不到进入重复阻塞,如果阻塞时间超过连接时间,解除阻塞,线程中断,抛出异常InterruptedException。

  • 步骤3:解锁

redis与Hadoop哪个好 redis和redisson_redis_09


流程

第一个if判断KEYS[1]是否存在,ARGV[3]的标记是否相同(防止释放错锁),不存在返回nil。

第二个if判断KEYS[1]的可重入次数是否大于0,说明此key还要继续利用,不能释放,大于0重新设置过期时间,小于0的话,则释放KEY[1],并重新设置锁,通知阻塞线程获取锁。

-------------------------------------------------------xx-----------------------------------------------------------

执行release操作,调用acquire,被阻塞的线程继续获取锁。(查了资料,看了别的博主,此处还是弄不太懂,望老司机指点下)

redis与Hadoop哪个好 redis和redisson_redis_10


问题:如果获取锁的线程,锁的过期时间小于线程执行任务的时间,会导致线程还未执行完,锁就面临过期,被释放掉,其他线程获取锁,修改数据,造成数据的值对应不上

Watch dog:自动延期机制
一般锁的默认释放时间为30秒,线程获取锁的同时,后台会自动运行一个watch dog线程,来监视此锁,每隔10秒检查一下,如果此线程还拥有此锁,那么就延长10秒。

四、分布式锁存在的风险

如果存储key的那个节点挂了的话,就可能存在丢失锁的风险,导致出现多个客户端持有锁的情况:
1、客户端A从master获取锁。
2、在master将锁同步到slave之前,master宕机了(因为主从复制是异步的,所以宕机的时候,master有锁,slave无锁),然后主从切换,slave节点被晋级为master节点。
3、客户端B此时请求获取锁,发现原slave节点里没有锁,因此会创建锁并获取,此时会跟客户端A取到同一个锁,导致同一时刻不止一个线程获取到锁。

五、附图

redis与Hadoop哪个好 redis和redisson_redis与Hadoop哪个好_11


redis与Hadoop哪个好 redis和redisson_redis_12

六、结语

如果有不足或不对之处,劳烦各位看官帮忙指出,万分感谢!爱你们(笔芯)