- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
分布式锁架构设计方案 -02
2021-10-14
在上一篇博文: 分布式锁架构设计方案 -01,我为大家具体引见了如何实现一个完善、高功能的基于Redis的分布式锁方案,信任大家应当都能有所裨益。然后,在实际开发过程中,之前的方案还是存在一些问题,虽然我们习惯性的将它称之为分布式锁,但从严格意义上来说却并不算,由于这仅仅只是一个依托于分布式组件作为载体来实现的单点锁,换句话说,锁的容错性较差,一旦目标Redis节点宕机,或者产生网络抖动都有可能导致客户端无法顺当加锁而导致业务特别;甚至还有可能因主/从切换引发平安问题(比如客户端A、B同时猎取到目标锁资源)的情况消灭(因而不建议添加slave节点),由于这是一个彻彻底底的单点问题,是无法简约通过横扩Redis集群节点就能够处理的。
?
那么实现一个完善的分布式锁,则必需要同时满足以下3个特性:
容错性:避开单点问题;
可用性:避开产生死锁;
互斥性:锁资源未释放之前,其它客户端不得进行加锁。
RedLock架构
我们都晓得Zookeeper是一个典型的CP系统,是一个基于ZAB(Zookeeper Atomic Broadcast,原子广播)协议的强全都性两头件,当我们向leader写入数据时,会由leader担任向集群中的其他follower节点同步数据,当 半数以上集群节点同步确认完成后,一次数据写入操作才算是成功。那么基于类似这样的思想,Redis社区提出了RedLock算法。
?
RedLock的核心思想是什么?简而言之,我们首先需要部署N个单点Redis,务必保证这些Redis节点之间是完全相互独立的,没必要存在任何主/从复制,以及集群协调机制的介入;当客户端在尝试加锁时,需要满足同时至少
=(N1)+1
个Redis节点上都顺当加锁成功,才代表一次分布式加锁操作是成功的,反之加锁失败。通过这样的保障机制,则可以有效提升分布式锁的容错性和满足平安性,以及互斥性需求。
redlock全体架构
在此大家需要留意,在实现RedLock时需要恪守如下5个商定:
以毫秒为单位猎取当前时间;
使用相同的key和具有独一性的value(例如UUID+TID)挨次从每一个Redis节点中加锁。客户端需要设置连接、响应超时,并且超时时间应当锁失效时间。这样可以避开Redis宕机,客户端还在等待响应结果。假如Redis没有在单位时间内响应,客户端应当快速失败恳求另外的Redis;
当满足=N/2+1个节点加锁成功,且锁的使用时间失效时间时,才算加锁成功;
加锁成功后,key的真正有效时间等于有效时间减去猎取锁使用时间;
客户端加锁失败时,需要在全部Redis节点上进行解锁,以防止在某些Redis节点上加锁成功但客户端无响应或超时而影响其它客户端无法加锁。
透过源码看本质
这里我在jedis-distributed-lock项目中实现了RedLock,那么接下来我就简约的从源码层面为大家再巩固加深一些印象。首先,我们需要在加锁前后记录当前时间戳,用endTime-beginTime后即可以得出锁的使用时间。示例1-1:
@Override
public boolean tryLock(long time, TimeUnit unit) {
if (locks.size() 3) {
throw new JedisLockException(More than 3 redis nodes are required);
}
long beginTime = System.currentTimeMillis();//记录开头时间
// TODO 加锁规律处理
long endTime = System.currentTimeMillis() - beginTime;//猎取锁的使用时间
}
RedLock算法的核心实际上就是尝试挨次从全部的目标Redis节点上猎取锁资源,只是我们需要在加锁后记录结果,以便于最终推断这一次的分布式加锁能否真正成功。示例1-2:
locks.stream().filter(lock - Objects.nonNull(lock)).forEach(lock - {
boolean result;
try {
result = time == -1L ? lock.tryLock() : lock.tryLock(lockTime, TimeUnit.MILLISECONDS);
} catch (Throwable e) {
result = false;
}
if (result) {
acquir
文档评论(0)