分布式趋势
目前几乎很多大型网站及应用都是分布式部署的,分布式场景中我们也都会遇到一个非常重要的问题:数据一致性。正如分布式的盖理论说的一样:“任何一个分布式系统都无法同时满足一致性(一致性),可用性(可用性)和分区容错性(分区容忍),最多只能同时满足两项。”所以,很多系统在设计之初就要对这三者进行取舍。在互联网领域的绝大多数的场景中,都需要牺牲强一致性来换取系统的高可用性,系统往往只需要保证”最终一致性”,只要这个最终时间是在用户可以接受的范围内即可。
在很多场景中,我们为了保证数据的最终一致性,需要很多的技术方案来支撑,比如分布式事务,分布式锁,定时任务调度等,尽管Java提供了很多并发处理API,但这些API在分布式场景中就显得无能为力了。
所以针对分布式锁的实现我们需要借助别的工具,目前比较常用的有以下几种方案:
-
<李>基于数据库实现分布式锁李>
<李>基于缓存(复述,memcached, tair)实现分布式锁李>
<李>基于管理员实现分布式锁李>
本篇发文我们主要说下基于复述的分布式锁实战。
实际编写代码之前,我们说下首要条件
分布式锁可用的四个条件:
-
<李>互斥性。在任意时刻,只有一个客户端能持有锁。李>
<李>不会发生死锁。即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁。李>
<李>具有容错性。只要大部分的复述,节点正常运行,客户端就可以加锁和解锁。李>
<李>解铃还须系铃人。加锁和解锁必须是同一个客户端,客户端自己不能把别人加的锁给解了。李>
分布式锁实战步骤:
<强>编写ILock接口强>
<强>编写ILock接口实现强>
LockGetter抽象类
从图示我们可以看的出,通过LockGetter抽象类进行具体的加锁成功或则失败的具体业务走向。这一个思想同学们要谨记于心,能够熟练应用的话,他会使你在编程之路上走的更加顺畅。
此外,可以看的到,我们实际加锁就一行代码:能。集(fieldKey、价值“NX",“EX",秒);,这个组()方法一共有五个形参:
第一个参数为关键,我们使用键来当锁,因为关键是唯一的。
第二个参数为价值,我们传的是requestId,很多童鞋可能不明白,有关键作为锁不就够了吗,为什么还要用到价值?原因就是我们在上面讲到可靠性时,分布式锁要满足第四个条件解铃还须系铃人,通过给值赋值为requestId,我们就知道这把锁是哪个请求加的了,在解锁的时候就可以有依据.requestId可以使用UUID.randomUUID () .toString()方法生成。
第三个参数为nxxx,这个参数我们填的是NX,意思是如果不存在,即当关键不存在时,我们进行设置操作,若钥匙已经存在,则不做任何操作,
第四个参数为expx,这个参数我们传的是PX,意思是我们要给这个键加一个过期的设置,具体时间由第五个参数决定。