Redisson分布式锁设计方案
Posted 栗子~~
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redisson分布式锁设计方案相关的知识,希望对你有一定的参考价值。
文章目录
前言
如果您觉得有用的话,记得给博主点个赞,评论,收藏一键三连啊,写作不易啊^ _ ^。
而且听说点赞的人每天的运气都不会太差,实在白嫖的话,那欢迎常来啊!!!
Redisson分布式锁设计方案
01 重温分布式锁
分布式锁,也是一种锁机制,只不过是为了专门应对分布式环境而出现的,
它并不是一种全新的组件或者中间件,它只是一种机制,一种实现方式,即解决方案而已。
它是用来保证在分布式的环境下,通过锁机制让多个客户端或者多个服务进程互斥地对"共享资源"进行访问,从而避免出现并发安全、数据不一致等问题。
01::01 分布式锁的设计的几点要求
业界普遍有几点要求:
- 排他性
- 避免死锁
- 高可用
- 可重入
- 公平锁(可选)
01::02 分布式锁要如何理解?
即通过第三方带有原子性的行为来保护高并发下的安全问题。
可能这句话对初学者有点绕口,没关系,记下来,会有帮助的。
02 Redisson分布式锁设计的优点
Redisson分布式锁解决了采用基于redis原子性操作实现分布式锁方式的缺陷。
02::01 Redis分布式锁设计的不足
- 执行Redis的原子操作时、要设置EXPIRE,即Reds的key的TTL,不同的业务场景设置的过期时间是不同的,如果设置不当,很可能会影响系统与Redis服务的性能。
- Redis 原子操作SETNX获取分布式锁的时候没有"可重入"特性,即当一个线程获得锁时,其他线程获取锁失败,永久的失败,本质上来说是没毛病的,但有些业务场景可能要求线程具有"可重入"特性,这时候,SETNX操作就不满足于当下的需求,就得需要一些配套的逻辑进行处理,即while(true)的代码,但这种方式即不优雅,也很有可能造成应用系统"卡顿"的风险。
- 当Redis原子性操作在【SETNX之后、EXPIPR之前】时,Reids服务发生宕机,同时应用服务出现问题导致该key未被删除,那么造成的影响最终会出现死锁线程,即永远没有线程可以获取到该key值的锁(未加TTL的同时锁也未被删除,导致其永久存在)。
03 Redisson分布式锁的功能特性
- 可重入锁
- 公平锁
- 联锁
- 红锁
- 读写锁
- 信号量及闭锁
04 Redisson分布式锁(可重入锁)实战
可重入锁分为一次性和可重入,顾名词义,一次性代表着当前线程如果可以获取到分布式锁,如果成功,获取之,失败则永久失败,可重入代表着当当前线程没有获取到分布式锁的时候,它并不会立即失败,而是等待一段时间重新获取。
04::01 Redisson分布式锁(可重入锁)一次性锁实战
代码如下:
@Autowired
private RedissonClient redissonClient;
/**
* Redission 分布式锁设计(一次性锁)
* */
@ApiOperation(value = "Redission 分布式锁设计(一次性锁)",notes = "Redission 分布式锁设计(一次性锁)")
@ResponseBody
@PostMapping("/onelock")
public ResponseBo onelock(String key)
String msgValue = "onelock";
long startTime = init(msgValue,key);
//分布式锁名称
final String lockName = "redissonOneLock-"+key;
RLock lock = redissonClient.getLock(lockName);
try
//尝试加锁, 上锁后10秒自动解锁
lock.lock(10,TimeUnit.SECONDS);
this.info("获取到一次性分布式锁");
this.info("执行业务逻辑");
endLog(msgValue,startTime);
return ResponseBo.ok();
catch (Exception e)
endLogError(msgValue,startTime,e);
return ResponseBo.error("保存失败" + e.getMessage());
finally
/**
* 注:访问共享资源结束后要释放锁
* */
if (lock!= null)
this.info("释放分布式锁");
lock.unlock();
//注在某些严格的业务场景下,也可以调用强制释放分布式锁的方法
//lock.forceUnlock();
测试:
04::02 Redisson分布式锁(可重入锁)可重入锁实战
代码如下:
@Autowired
private RedissonClient redissonClient;
/**
* Redission 分布式锁设计(可重入锁)
* */
@ApiOperation(value = "Redission 分布式锁设计(可重入锁)",notes = "Redission 分布式锁设计(可重入锁)")
@ResponseBody
@PostMapping("/trylock")
public ResponseBo trylock(String key)
String msgValue = "trylock";
long startTime = init(msgValue,key);
//分布式锁名称
final String lockName = "redissonTryLock-"+key;
RLock lock = redissonClient.getLock(lockName);
try
//尝试加锁, 最多等待100秒,上锁后10秒自动解锁
Boolean aBoolean = lock.tryLock(100,10,TimeUnit.SECONDS);
if (aBoolean)
this.info("获取到可重入分布式锁");
this.info("执行业务逻辑");
endLog(msgValue,startTime);
return ResponseBo.ok();
catch (Exception e)
endLogError(msgValue,startTime,e);
return ResponseBo.error("保存失败" + e.getMessage());
finally
/**
* 注:访问共享资源结束后要释放锁
* */
if (lock!= null)
this.info("释放分布式锁");
lock.unlock();
//注在某些严格的业务场景下,也可以调用强制释放分布式锁的方法
//lock.forceUnlock();
测试:
以上是关于Redisson分布式锁设计方案的主要内容,如果未能解决你的问题,请参考以下文章
Spring Schedule+Redisson分布式锁构建分布式任务调度