RedisTemplate下复述分布式锁引发的系列问题有哪些

  介绍

这篇文章主要介绍了RedisTemplate下复述分布式锁引发的系列问题有哪些,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获、下面让小编带着大家一起了解一下。

,,,首先,分布式集群的问题大家都知道,会造成数据库的插入重复问题,会造成一系列的并发性问题。

,,,解决的方式呢也大概如下几点,百度以及谷歌上都能搜到的解决方式:

,,,1:数据库添加唯一索引

,,,2:设计接口幂等性

,,,3:依靠中间件使用分布式锁,而分布式锁又分为复述和饲养员

,,由于管理员我没怎么接触过,并且我项目中本来就引用了复述,所以就想着用复述来做分布式锁,也高端洋气上档次点。

,,首先基于复述的操作,我们必须要保证其原子性,也就是要么全部成功,要么全部失败,先从复述的客户端入手。

,,就复述,客户端而言,我们通过的操作是先使用setnx指令,如果成功则返回1,失败则返回0

 RedisTemplate下复述分布式锁引发的系列问题有哪些

,,可是就分布锁锁而言,一个常用的问题就是如果一个服务setnx成功了,但是在解锁的时候如果发生了宕机或者一些特殊因素,导致无法解锁,那么其他服务将陷入死锁的状态,所以,我们在用setnx的同时想着去用到期指令对锁进行一个过期操作

,  RedisTemplate下复述分布式锁引发的系列问题有哪些

,,从指令可以看出setnx和到期指令是分开的,如果在这中间的空隙过程中如果有特殊因素导致指令无法继续,也会导致死锁的产生。

以下参考自老钱的,复述,深度历险:核心原理与应用实践

,,为了解决这个疑难,复述,开源社区涌现了一堆分布式锁的图书馆,专门用来解决这个问题。实现方法极为复杂,小白用户一般要费很大的精力才可以搞懂。如果你需要使用分布式锁,意味着你不能仅仅使用能或者redis-py就行了,还得引入分布式锁的图书馆。

,,为了治理这个乱象,复述,2.8版本中作者加入了套指令的扩展参数,使得setnx和到期指令可以一起执行,彻底解决了分布式锁的乱象。从此以后所有的第三方分布式锁库可以休息了。

,, RedisTemplate下复述分布式锁引发的系列问题有哪些

,以上都是基于复述的操作,但是我们在JAVA中如何去运用分布式锁呢。

,首先在复述,方面我用的是RedisTemplate对复述,进行操作的,,而RedisTemplate在目前情况下如果不借助于是无法保证其原子性的,所以我们需要借助于复述的Lua脚本。

,,先上Lua脚本的代码

//,加锁   if    ,,,redis.call (& # 39; setNx& # 39;键[1],ARGV [1]),   then 才能;   ,,,if  redis.call(& # 39;得到# 39;键[1])==ARGV [1],   ,,,return  redis.call(& # 39;到期# 39;键[1],ARGV [2]),   else 才能;   ,,,return  0,   最终获得才能;   结束   ,//,解锁   redis.call才能(& # 39;得到# 39;,,键[1]),==,ARGV [1],   then    return 才能;redis.call(& # 39;德尔# 39;,,键[1]),   else    return 才能;0

,,,Java调用脚本有两种方式

,1。新建一个脚本文件,在代码中调用其绝对路径地址

,,redisScript。setScriptSource(新ResourceScriptSource(新ClassPathResource(地址))),

,2。在Java代码中以字符串的方式传入

,,redisScript.setScriptText(脚本);

,我是用的第二种方式实现的,下面是JAVA代码

/* *   ,,*,获取锁   ,,*,@param  lockKey   ,,*,@param 价值   ,,*,@param  expireTime:单位——秒   ,,* @return   ,,*/public 才能;boolean  getLock (String  lockKey, String 价值,int  expireTime) {   ,,,boolean  ret =,假;   ,,,试着{   ,,,,,String  script =,“if  redis.call (& # 39; setNx& # 39;键[1],ARGV [1]), then  if  redis.call(& # 39;得到# 39;键[1])==ARGV [1], then  return  redis.call(& # 39;到期# 39;键[1],ARGV [2]), else  return  0,最终获得以何种;;   ,   ,,,,,RedisScript, redisScript =, new  DefaultRedisScript<祝辞(脚本,,Long.class);   ,   ,,,,,Object  result =, redisTemplate.execute (redisScript new  StringRedisSerializer (), new  StringRedisSerializer (),, Collections.singletonList (lockKey),价值,expireTime  +,““);   ,,,,,System.out.println(时间+ result “- - - - - - - - - - -产生绯闻;);   ,,,,,//Object  result =, redisTemplate.execute (redisScript, Collections.singletonList (lockKey),价值,expireTime  +,““);   ,   ,,,,,如果(SUCCESS.equals(结果)){   ,,,,,,,return 真实;   ,,,,,}   ,   ,,,}捕捉(Exception  e) {   ,,,,,e.printStackTrace ();   ,,,}   ,,,return 回收;   ,,}   ,   ,/* *   ,,*,释放锁   ,,*,@param  lockKey   ,,*,@param 价值   ,,* @return   ,,*/public 才能;boolean  releaseLock (String  lockKey, String 价值){   ,   null   null   null   null   null   null   null   null   null   null   null

RedisTemplate下复述分布式锁引发的系列问题有哪些