Redisson实现分布式锁(1)---原理

Redisson实现分布式锁(1)---原理

有关Redisson做为实现分布式锁,总的分3大模块来说。java

一、Redisson实现分布式锁原理
二、Redisson实现分布式锁的源码解析
三、Redisson实现分布式锁的项目代码(能够用于实际项目中)

本文只介绍Redisson如何实现分布式锁的原理。其它的会在接下来的博客讲,最后有关Redisson实现分布式锁的项目代码的博客中会放上项目源码到GitHub上。redis

1、高效分布式锁

当咱们在设计分布式锁的时候,咱们应该考虑分布式锁至少要知足的一些条件,同时考虑如何高效的设计分布式锁,这里我认为如下几点是必需要考虑的。数据库

一、互斥

在分布式高并发的条件下,咱们最须要保证,同一时刻只能有一个线程得到锁,这是最基本的一点。服务器

二、防止死锁

在分布式高并发的条件下,好比有个线程得到锁的同时,尚未来得及去释放锁,就由于系统故障或者其它缘由使它没法执行释放锁的命令,致使其它线程都没法得到锁,形成死锁。并发

因此分布式很是有必要设置锁的有效时间,确保系统出现故障后,在必定时间内可以主动去释放锁,避免形成死锁的状况。异步

三、性能

对于访问量大的共享资源,须要考虑减小锁等待的时间,避免致使大量线程阻塞。分布式

因此在锁的设计时,须要考虑两点。高并发

一、锁的颗粒度要尽可能小。好比你要经过锁来减库存,那这个锁的名称你能够设置成是商品的ID,而不是任取名称。这样这个锁只对当前商品有效,锁的颗粒度小。性能

二、锁的范围尽可能要小。好比只要锁2行代码就能够解决问题的,那就不要去锁10行代码了。ui

四、重入

咱们知道ReentrantLock是可重入锁,那它的特色就是:同一个线程能够重复拿到同一个资源的锁。重入锁很是有利于资源的高效利用。关于这点以后会作演示。

针对以上Redisson都能很好的知足,下面就来分析下它。


2、Redisson原理分析

为了更好的理解分布式锁的原理,我这边本身画张图经过这张图来分析。

一、加锁机制

线程去获取锁,获取成功: 执行lua脚本,保存数据到redis数据库。

线程去获取锁,获取失败: 一直经过while循环尝试获取锁,获取成功后,执行lua脚本,保存数据到redis数据库。

二、watch dog自动延期机制

这个比较难理解,找了些许资料感受也并无解释的很清楚。这里我本身的理解就是:

在一个分布式环境下,假如一个线程得到锁后,忽然服务器宕机了,那么这个时候在必定时间后这个锁会自动释放,你也能够设置锁的有效时间(不设置默认30秒),这样的目的主要是防止死锁的发生。

但在实际开发中会有下面一种状况:

//设置锁1秒过去
        redissonLock.lock("redisson", 1);
        /**
         * 业务逻辑须要咨询2秒
         */
        redissonLock.release("redisson");

      /**
       * 线程1 进来得到锁后,线程一切正常并无宕机,但它的业务逻辑须要执行2秒,这就会有个问题,在 线程1 执行1秒后,这个锁就自动过时了,
       * 那么这个时候 线程2 进来了。那么就存在 线程1和线程2 同时在这段业务逻辑里执行代码,这固然是不合理的。
       * 并且若是是这种状况,那么在解锁时系统会抛异常,由于解锁和加锁已经不是同一线程了,具体后面代码演示。
       */

因此这个时候看门狗就出现了,它的做用就是 线程1 业务尚未执行完,时间就过了,线程1 还想持有锁的话,就会启动一个watch dog后台线程,不断的延长锁key的生存时间。

注意 正常这个看门狗线程是不启动的,还有就是这个看门狗启动后对总体性能也会有必定影响,因此不建议开启看门狗。

三、为啥要用lua脚本呢?

这个不用多说,主要是若是你的业务逻辑复杂的话,经过封装在lua脚本中发送给redis,并且redis是单线程的,这样就保证这段复杂业务逻辑执行的原子性

四、可重入加锁机制

Redisson能够实现可重入加锁机制的缘由,我以为跟两点有关:

一、Redis存储锁的数据类型是 Hash类型
二、Hash数据类型的key值包含了当前线程信息。

下面是redis存储的数据

这里表面数据类型是Hash类型,Hash类型至关于咱们java的 <key,<key1,value>> 类型,这里key是指 'redisson'

它的有效期还有9秒,咱们再来看里们的key1值为078e44a3-5f95-4e24-b6aa-80684655a15a:45它的组成是:

guid + 当前线程的ID。后面的value是就和可重入加锁有关。

举图说明

上面这图的意思就是可重入锁的机制,它最大的优势就是相同线程不须要在等待锁,而是能够直接进行相应操做。

五、Redis分布式锁的缺点

Redis分布式锁会有个缺陷,就是在Redis哨兵模式下:

客户端1 对某个master节点写入了redisson锁,此时会异步复制给对应的 slave节点。可是这个过程当中一旦发生 master节点宕机,主备切换,slave节点从变为了 master节点。

这时客户端2 来尝试加锁的时候,在新的master节点上也能加锁,此时就会致使多个客户端对同一个分布式锁完成了加锁。

这时系统在业务语义上必定会出现问题,致使各类脏数据的产生

缺陷在哨兵模式或者主从模式下,若是 master实例宕机的时候,可能致使多个客户端同时完成加锁。


说明 这篇博客主要是根据本身的开发经验,同时也在网上找了许多资料后整理的,若是哪里有写的不对,但愿多多指点。万分感激!




只要本身变优秀了,其余的事情才会跟着好起来(中将5)
相关文章
相关标签/搜索