这篇文章主要介绍了RedisTemplate下复述分布式锁引发的系列问题有哪些,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获、下面让小编带着大家一起了解一下。
,,,首先,分布式集群的问题大家都知道,会造成数据库的插入重复问题,会造成一系列的并发性问题。
,,,解决的方式呢也大概如下几点,百度以及谷歌上都能搜到的解决方式:
,,,1:数据库添加唯一索引
,,,2:设计接口幂等性
,,,3:依靠中间件使用分布式锁,而分布式锁又分为复述和饲养员
,,由于管理员我没怎么接触过,并且我项目中本来就引用了复述,所以就想着用复述来做分布式锁,也高端洋气上档次点。
,,首先基于复述的操作,我们必须要保证其原子性,也就是要么全部成功,要么全部失败,先从复述的客户端入手。
,,就复述,客户端而言,我们通过的操作是先使用setnx指令,如果成功则返回1,失败则返回0
,,可是就分布锁锁而言,一个常用的问题就是如果一个服务setnx成功了,但是在解锁的时候如果发生了宕机或者一些特殊因素,导致无法解锁,那么其他服务将陷入死锁的状态,所以,我们在用setnx的同时想着去用到期指令对锁进行一个过期操作
,
,,从指令可以看出setnx和到期指令是分开的,如果在这中间的空隙过程中如果有特殊因素导致指令无法继续,也会导致死锁的产生。
以下参考自老钱的,复述,深度历险:核心原理与应用实践
,,为了解决这个疑难,复述,开源社区涌现了一堆分布式锁的图书馆,专门用来解决这个问题。实现方法极为复杂,小白用户一般要费很大的精力才可以搞懂。如果你需要使用分布式锁,意味着你不能仅仅使用能或者redis-py就行了,还得引入分布式锁的图书馆。
,,为了治理这个乱象,复述,2.8版本中作者加入了套指令的扩展参数,使得setnx和到期指令可以一起执行,彻底解决了分布式锁的乱象。从此以后所有的第三方分布式锁库可以休息了。
,,
,以上都是基于复述的操作,但是我们在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下复述分布式锁引发的系列问题有哪些