重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
目前几乎很多大型网站及应用都是分布式部署的,分布式场景中我们也都会遇到一个非常重要的问题:数据一致性。正如分布式的CAP理论说的一样:“任何一个分布式系统都无法同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance),最多只能同时满足两项。”所以,很多系统在设计之初就要对这三者进行取舍。在互联网领域的绝大多数的场景中,都需要牺牲强一致性来换取系统的高可用性,系统往往只需要保证“最终一致性”,只要这个最终时间是在用户可以接受的范围内即可。
在很多场景中,我们为了保证数据的最终一致性,需要很多的技术方案来支撑,比如分布式事务、分布式锁、定时任务调度等。尽管Java提供了很多并发处理API,但这些API在分布式场景中就显得无能为力了。
所以针对分布式锁的实现我们需要借助别的工具,目前比较常用的有以下几种方案:
本篇发文我们主要说下基于Redis的分布式锁实战。
实际编写代码之前,我们说下首要条件
编写ILock接口
编写ILock接口实现
LockGetter抽象类
从图示我们可以看出,通过LockGetter抽象类进行具体的加锁成功或则失败的具体业务走向。这一个思想同学们要谨记于心。能够熟练应用的话,他会使你在编程之路上走的更加顺畅。
此外,可以看到,我们实际加锁就一行代码:jedis.set(fieldKey, value, "NX", "EX", seconds);,这个set()方法一共有五个形参:
第一个参数为key,我们使用key来当锁,因为key是唯一的。
第二个参数为value,我们传的是requestId,很多童鞋可能不明白,有key作为锁不就够了吗,为什么还要用到value?原因就是我们在上面讲到可靠性时,分布式锁要满足第四个条件解铃还须系铃人,通过给value赋值为requestId,我们就知道这把锁是哪个请求加的了,在解锁的时候就可以有依据。requestId可以使用UUID.randomUUID().toString()方法生成。
第三个参数为nxxx,这个参数我们填的是NX,意思是SET IF NOT EXIST,即当key不存在时,我们进行set操作;若key已经存在,则不做任何操作;
第四个参数为expx,这个参数我们传的是PX,意思是我们要给这个key加一个过期的设置,具体时间由第五个参数决定。
第五个参数为time,与第四个参数相呼应,代表key的过期时间。
总的来说,执行上面的set()方法之后会出现两种情况:
使用缓存来实现分布式锁优点:
使用缓存实现分布式锁尽管性能好,实现起来较为方便。但也不是没有缺点,有时候我们的程序内部出现异常后可能会发生死锁,这就需要开发时候注意代码编写,后续测试人员测试时候测试案例要尽可能覆盖。
另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。