目录
一、分布式锁的特征
二、redis手写简单分布式锁
三、redission实现分布式锁
1.redission实现分布式锁的原理
2. redission实现自动续期 - watch dog机制
3. redission实现可重入机制的原因
4. redission实现分布式锁存在问题?
5. 如何解决?redLock红锁
6. redission实现分布式锁核心代码
1. 独占排它使用(setnx)
2. 防止死锁发生(设置过期时间;不可重入:方法a和b嵌套且使同一把锁,ReentLock可重入)
3. 防误删(先判断再删除)
4. 原子性(通过lua脚本获取、判断、释放三着实现原子性)
5. 可重入(hash+lua)
6. 自动续期(定时任务重置过期时间)
先setnx key value,再expire key seconds无法保证原子性
1.使用set...nx... 命令(setIfAbsent函数),将加锁、过期命令编排到一起保证原子操作了,避免死锁
2. 使用lua脚本,保证判断锁、删除锁三者要保证原子性(通过execute函数回调),避免误删锁
以上代码基本实现简单的分布式锁,但是没有保证可重入性和锁的自动续期
线程获取锁成功后,通过执行lua脚本,保存数据到数据库
线程获取锁失败后,会通过while一直尝试获取锁,直到成功
加锁成功后,守护线程开启看门狗机制,lock.lock(),不加过期时间会触发看门狗机制,看门狗机制提供的超时时间默认30s,在锁还存在的前提前,自定续期,每10s巡查一次,即每10s将自动释放锁的过期时间刷新为30s
如果自定义了失效时间的话,无论是通过lock还是tryLock,都无法触发看门狗机制
redis存储锁的数据类型为hash,即
在redis哨兵模式下
客户端1,对master节点写入了redisson锁,此时会异步复制给对应的 slave节点。但是这个过程中一旦发生 master节点宕机,哨兵选举,主备切换,slave节点从变为了 master节点
客户端2,此时来尝试加锁,在新的master节点上也能加锁,此时导致多个客户端对同一个分布式锁完成加锁
redLock红锁,分布式锁相对安全的一种实现方式,采用主节点过半机制
核心思路:
几个独立的master节点,推荐是5个,然后逐个加锁,只要超过一半节点(5/2 +1 = 3)加锁成功就表示加锁成功,释放的时候逐个释放。
基于redis的redission红锁RedissionRedLock实现RedLock介绍的加锁算法,该对象可以用来将对各RLock对象关联成一个红锁,每个RLock对象可以来自不同的redission实例
RLock lock1 = redissonInstance1.getLock("lock1");
RLock lock2 = redissonInstance2.getLock("lock2");
RLock lock3 = redissonInstance3.getLock("lock3");
RedissonRedLock lock = new RedissonRedLock(lock1, lock2, lock3);
// 同时加锁:lock1 lock2 lock3
// 红锁在大部分节点上加锁成功就算成功。
lock.lock();
...
lock.unlock();
a, 编写RdissionConfig类并手动配置注入@Bean RedissionClient到spring IOC容器
b. Rlock rlock = redissionClient.get("lock");
c. rlock.lock();
d. 业务逻辑
e. lock.unlock();
springboot继承redission链接:springboot 集成redission分布式锁_人生就像一场戏!的博客-CSDN博客_redission springboot
redission实现分布式锁的原理链接:https://www.cnblogs.com/hanease/p/15922813.html