redis缓存工具Jedis进行跨jvm加锁(分布式应用)–不幸暂弃用–能够做第三方锁使用…

redis缓存工具Jedis进行跨jvm加锁(分布式应用)–不幸暂弃用–能够做第三方锁使用…

       近期使用redis碰到了多个并发处理同一个缓存的情况。在这样的情况下须要进行加锁机制。

本来想使用java自带的ReadWriteLock进行设置读写锁,这也是上家公司使用的方法。

后来经过商讨,给予排除。原因无他,就是java自带的并不能跨jvm进行加锁,意思就是说Aserver上的write锁无法限制Bserver上的同一个方法,也就是说不适用于分布式部署的环境。

        后来经过多方面查看资料。终于决定使用redis自身的方法setnx来进行加锁机制。

网上有非常多关于setnx来进行加锁的方法。只是大部分都会有一个同样的缺陷。就是直接使用setnx加锁、使用del释放锁。这样的情况下呢。假设加锁后发生异常导致没有释放锁,则会成为死锁。

參考:http://blog.csdn.net/java2000_wl/article/details/8740911

        再后来有一种新的思路,将setnx和expire结合使用,使得锁有一个有效期,这样当发生异常。有效期一过能够自己主动释放锁。这个算是有一些改进。只是因为setnx和expire是两步操作,不具有原子性。假设setnx操作之后发生异常。还是会造成死锁。

        然后就考虑有什么办法能够使得setnx和expire操作同步实现并具有原子性。那么转换一下思路,将setnx的value值设置成当前时间过后的某一刻时间(比方1分钟之后),这个是不是就能够间接取代expire操作了。

是的,这样的方式能够实现。

那么如今就是这样的方式加上del基本能够实现加锁和解锁(而且能够解因异常为释放的锁)。

仅仅只是仍有一些缺陷。由于这样的情况会造成竞争关系,參照:https://github.com/huangz1990/redis/commit/18dbaee4f40f435970a09da427b8f45bd26b4072#diff-b643df753e12d0d07a872f91487c957dR34

         依据上面链接给出的解决的方法(即新算法思路)使用有效期来推断之后不是删除key,而是直接给key赋予新值,使用getset,然后推断得到的值和原来的值是否相等。相等即获得锁。最后提供了手动解锁的方法(即删除key就能够)。以下给出代码:

public boolean lock(String key, long timeout) {
		boolean lockSuccess = false;
		ShardedJedis shardedJedis = pool.getResource();
		try{
			long start = System.currentTimeMillis();
			String lockKey = "lock_"+key;
			do{
				long result = shardedJedis.setnx(lockKey, String.valueOf(System.currentTimeMillis()+LOCKKEY_EXPIRE_TIME*1000+1));
				if(result == 1){
					lockSuccess = true;
					break;
				}else{
					String lockTimeStr = shardedJedis.get(lockKey);
					if(StringUtils.isNumeric(lockTimeStr)){//假设key存在。锁存在
						long lockTime = Long.valueOf(lockTimeStr);
						if(lockTime < System.currentTimeMillis()){//锁已过期
							String originStr = shardedJedis.getSet(lockKey, String.valueOf(System.currentTimeMillis()+LOCKKEY_EXPIRE_TIME*1000+1));
							if(StringUtils.isNoneBlank(originStr)&&originStr.equals(lockTimeStr)){//表明锁由该线程获得
								lockSuccess = true;
								break;
							}
						}
					}
				}
				//假设不等待,则直接返回
				if(timeout == 0){
					break;
				}
				//等待300ms继续加锁
				Thread.sleep(300);
			}while((System.currentTimeMillis()-start) < timeout);

		}catch(Exception e){
			e.printStackTrace();
		}finally{
			...
		}
		return lockSuccess;
	}

	public void unLock(String key) {
		ShardedJedis shardedJedis = pool.getResource();
		try{
			String lockKey = "lock_"+key;
			shardedJedis.del(lockKey);
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			...
		}
	}

       大概就这些吧~~~

共勉!

——补充:

     后来在实际应用其中,用代码測试了一下:使用5000并发线程进行加锁操作,会报非常多的connect timeout异常,因为setnx也是在操作redis和redis进行连接,会占用Jedis连接池中的连接,并且没有获得锁的线程一直在等待。所以我们临时弃用。并且redis是单线程的,读写效率都非常高。除非一些特殊业务须要严格的数据同步,否则redis也不须要加锁。

所以等以后碰到这样的特殊业务再具体学习并慎重使用吧。

     特意写出来,防止误导别人~~

——-再补充:

     事实上redis本身不须要加锁,须要加锁的是进行redis操作之前的数值计算等,这就须要进行锁控制了。而对于这样的是能够考虑使用redis加锁的。仅仅须要给加锁的redis单独起一个实例就可以,初期这样部署会有资源的浪费。中后期能够这样操作。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/109136.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Cydia中文源_最新cydia源地址大全

    Cydia中文源_最新cydia源地址大全Cydia中文源大全cydia.hackulo.us大名鼎鼎的Hackulo源,资源不多,但都几乎是必须的,我的appsync,Installous等一般就在这里面进行安装如果你要装googlemap补丁,就要加/julio-skype/macanavari//omkff//iPhone-I//suik/无语资源仓iphone.**.com/cydia/电玩扒屎的Cydia源,资源丰…

    2022年9月20日
    0
  • 磁盘,硬盘,软盘,光盘的区别[通俗易懂]

    磁盘,硬盘,软盘,光盘的区别[通俗易懂]计算机存储器分为两大类:内存存储器和外部存储器(简称内存或内存条和外存)。内存容量小,存取速度快,只能临时保存信息(经cup处理后的数据),断电后信息就会消失。外存容量大,存取速度比内存慢,能永久

    2022年8月3日
    3
  • 几个关于silverlight的网站[通俗易懂]

    几个关于silverlight的网站[通俗易懂]1.  示例     http://silverlightnuggets.com/ 2. Silverlight示例    http://silverlight.net/community/communitygallery.aspx 3. http://silverlight.net/Learn/ 

    2022年10月19日
    0
  • 中星睿典职称计算机考试,大纲教材 – 中星睿典 – 全国职称计算机考试|职称计算机考试模块|全国职称计算机考试试题…

    中星睿典职称计算机考试,大纲教材 – 中星睿典 – 全国职称计算机考试|职称计算机考试模块|全国职称计算机考试试题…大纲教材介绍全国专业技术人员计算机应用能力考试,又称全国职称计算机应用考试。为贯彻党的十五届五中全会提出的“要在全社会广泛应用信息技术,全国职称计算机考试可以提高计算机和网络的普及应用程度,加强信息资源的开发和利用”的精神,落实国家加快信息化建设的要求,引导全国专业技术人员学习掌握计算机知识,提高计算机的应用能力,根据原人事部《关于全国专业技术人员计算机应用能力考试的通知》(人发2001124号)…

    2022年6月2日
    30
  • 二进制、八进制、十进制、十六进制关系及转换[通俗易懂]

    二进制、八进制、十进制、十六进制关系及转换[通俗易懂]二进制,八进制,十进制,十六进制之间的关系是什么?浮点数是什么回事?本文内容参考自王达老师的《深入理解计算机网络》一书&amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;中国水利水电出版社&amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;一、数制解释:1、编程中经常使用的数制分类(“你编程时能使用的数制全部在这里了”):⑴、十进制十进制是我们生活中使用得最频繁的进制了。十进制的基数是10,也就是说,十进制有10个数字符

    2022年10月17日
    1
  • 电压电流转换电路[通俗易懂]

    电压电流转换电路[通俗易懂]前言:昨天看到一篇介绍输出4~20mA电流电路的文章。作者首先介绍了两个直接用运放和三极管搭起来的电路,但并没有给出原理介绍,然后给出了第三种使用集成芯片的电路,并推荐大家使用。不可否认,作为商业产品,集成电路性能优异且更加稳定,方便工程师使用。但是笔者却突然想到了前几天某公司被美国商务部制裁的事件,如果中国的工程师都是“拿来主义”,只会照着参考电路做设计,我们就会永远受制于人,而且对工程师的成长

    2022年6月2日
    36

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号