一、引言
我们先来谈谈分布式锁,为什么要有分布式锁呢? 实现 jdk 提供的 synchronized、lock 等锁不是很好吗? 这是因为在单进程的情况下,多个线程访问同一个资源,可以使用 synchronized 和 lock 来实现; 在多个进程的情况下,即在分布式的情况下,需要使用分布式锁来实现对同一资源的并发请求。 Redisson 组件可以实现 Redis 的分布式锁,Redisson 也是官方推荐的 Redis 分布式锁实现方案,封装后让用户实现分布式锁更加方便简洁。
2. 分布式锁的特点
相互排斥任何时候,只有一个客户端可以获取一个锁,并且没有两个客户端可以同时获取一个锁。 身份锁只能由持有锁的客户端删除,不能由其他客户端删除。 重入持有锁的客户端可以继续锁定锁并续订锁。 容错当一个锁失败(超过其生命周期结束时)时,锁会自动释放(密钥无效),其他客户端可以继续获取该锁以防止死锁。 3. Redisson分布式锁原理
在下文中,我们从五个方面分析了雷迪森分布式锁的原理:锁机制、锁互斥机制、锁更新机制、可重入锁机制和锁释放机制。
3.0 整体分析
注意:Redisson 版本 324.4-snapshot
**微信***老周聊天架构】*公共类RedissonLockTest终于 }
初始化 redissonlock
** 锁定方式 * param leasetime 锁定过期时间(-1:使用默认值 30 秒) *param 单位时间单位 * param 可以中断 * 抛出 interruptedException * private void lock(long leasetime, timeunit unit, boolean interruptibly) 抛出 interruptedexception 订阅分布式锁,解锁时通知。 completablefuture future = subscribe(threadid); pubsub.timeout(future); redissonlockentry entry;如果 (interruptablely) else try waiting for message 如果锁过期时间大于零,则执行具有过期时间的阻塞取取。 if (ttl >= 0) catch (interruptedexception e) entry.getlatch().tryacquire(ttl, timeunit.milliseconds); else else }finally }
当锁定超时时间为 -1 且成功获取锁定时,将启动看门狗定时任务,自动续订锁定
每次续锁时,都需要判断锁是否已经松开,如果续锁成功,您将再次安排自己继续续锁操作。
为了保证原子性,见31 锁定机构。
3.1 锁定机构。
锁定机制的核心就是这一部分,其中 lua 脚本被包裹在 redisoon 中,最后通过 netty 传输。
rfuture trylockinnerasync(long waittime, long leasetime, timeunit unit, long threadid, redisstrictcommand command)
当你去一个波时,断点很清楚:
keys[1]) 键ar**[1]:密钥的存活时间,默认为 30 秒。
ar**[2]:锁定的客户端 ID (uuidrandomuuid())threadid)
上一段中带锁的 lua 脚本的作用是:第一个 if 判断语句是使用 exists mylock 命令来判断,如果要锁定的锁键不存在(第一个锁)或者键的字段存在(reentrant lock),则将其锁定。 如何锁定它? 使用 hincrby 命令设置哈希结构,类似于在 Redis 中执行的操作,如下所示:
整个 lua 脚本锁定过程如下图所示:
如您所见,最新版本的逻辑比以前的版本更简单、更清晰。
3.2 锁定互斥机制
此时,如果客户端 2 尝试锁定它,该怎么办? 首先,第一个 if 判断将执行存在 mylock,并且会发现锁键 mylock 已经存在。 那么第二个if判断就是判断mylock锁键的哈希数据结构是否包含客户端2的ID,这显然不是,因为它包含了客户端1的ID。 因此,客户端 2 执行:
return redis.call('pttl', keys[1]);
返回的数字,表示 mylock 密钥的剩余生存时间。
锁互斥机制实际上是主要过程3.0 整体分析你可以看到这个组织redisson.redissonlock#lock(long, j**a.util.concurrent.timeunit,布尔值)。
3.3 锁仓续期机制
客户端 1 添加的锁键默认生存时间为 30 秒,如果超过 30 秒,客户端 1 想要保留锁应该怎么做?
Redisson 提供了一种续订机制,该机制在客户端 1 被锁定后立即启动看门狗。
3.4 再入锁定机构
看门狗机制实际上是一个后台调度任务线程,在成功获取锁后,持有锁的线程会被放入一个redissonbaselock中过期续费映射,然后每 10 秒检查一次(internallockleasetime 3),客户端 1 是否仍然持有锁键(判断客户端是否还持有密钥,其实就是遍历过期续费映射中的线程 ID,然后根据线程 ID 在 redis 中检查,如果存在, 钥匙的时间会延长),然后锁会不断延长钥匙的寿命。
注意:3.5 锁定释放机制如果服务宕机,看门狗机制线程会消失,密钥的过期时间不会延长,30s后会自动过期,其他线程可以拿到锁。
如果调用具有过期时间的锁定方法,则监视程序任务不会启动以自动续订。
确定 keys[1] 中是否存在 ar**[3]。"if (redis.call('hexists', keys[1], ar**[3]) == 0) then " + "return nil;" +"end; "+ 替换 ar**[3] val - 1 中的键 [1]"local counter = redis.call('hincrby', keys[1], ar**[3], 1); "+ 如果返回值大于 0,则证明它是可重入锁"if (counter > 0) then "+ 重置过期时间"redis.call('pexpire', keys[1], ar**[2]);" + "return 0; " +"else "+ 删除键[1]。"redis.call('del', keys[1]);"+ 等待线程或进程资源可用的通知阻止"redis.call('publish', keys[2], ar**[1]);" + "return 1; " +"end; " +"return nil;"
keys[1]: mylock同样,锁释放断点也会出现波浪:keys[2]: redisson_lock_channel:
ar**[1]: 0
ar**[2]:30000(过期时间)。
ar**[3]: 66a84a47-3960-4f3e-8ed7-ea2c1061e4cf:1 (哈希中的锁定字段)。
锁释放机制摘要:
移除锁(注意此处的可重入锁)会广播一条消息以释放锁,通知阻塞等待过程(到名为 Redisson Lock Channel 的通道:发布解锁消息)以取消看门狗机制,即 RedissonLock删除到期续费映射中的线程 ID,并取消 Netty 的定时任务线程。
四、主从Redis架构中分布式锁的问题
线程 A 向主 Redis 请求分布式锁,并成功获取该锁。 当主 Redis 准备同步来自主 Redis 的锁信息时,主 Redis 突然关闭,锁丢失。 触发从 Redis 到新主 Redis 的升级; 线程 B 从后继 Redis 的 Slave Redis 申请分布式锁,可以成功获取该锁。 这样一来,两个客户端同时获取相同的分布式锁,没有独占使用功能; 为了解决这个问题,Redis 引入了红锁的概念。
您需要准备多个Redis实例,这些实例彼此完全独立,并且这些节点之间没有主从关系。 当客户端申请分布式锁时,需要向所有Redis实例发送一个应用,只有当超过一半的Redis实例报告锁已成功获取时,才能认为该锁已获得。 与大多数保证一致性的算法类似,这是多数原则。
public static void main(string args) finally }
当然,RedLock算法是毋庸置疑的,两位神仙在几年前就吵过架,有兴趣的话可以去Redis官网查看一下Martin Kleppmann和Redis作者Antirez的争论。
好吧,我想收集它,如果继续谈论它,我感觉我无法绕过分布式经典问题上限。
5. 分布式锁选择
如果想要强一致性,可以选择 zk 的分布式锁,但是 zk 的性能会在一定程度上下降,如果项目不使用 zk,那就选择 redis 的分布式锁,比较你的性能为那个非常小的概率,引入一个组件是不划算的,如果不能容忍 redis 的红锁缺陷, 然后你可以自己在业务中保证。
以下是几种常见的分布式锁选择的比较:
如果您喜欢这篇文章,请点击右上角与您的朋友分享文章。
想要了解学习的技术要点,请留言若飞安排分享。
由于***推送规则变更,请点击“观看”并添加“星标”,即可第一时间获得精彩技术分享
·end·
相关阅读:
了解微服务架构路线的图表:基于Spring Cloud的微服务架构分析:微服务等于Spring Cloud? 了解微服务架构和框架如何构建基于 DDD 的域驱动型微服务? 对于一个小团队来说,引入SpringCloud微服务真的很合适吗? DDD兴起的原因及其与微服务的关系调用微服务的最佳方式微服务架构设计总结基于Kubernetes的微服务项目设计与实现微服务架构-设计总结为什么微服务必须有网关? 主流微服务全链路监控系统之战,详细讲解了微服务架构的实现原理,微服务的介绍和技术栈,设计了微服务场景下的数据一致性解决方案,设计了容错微服务架构作者: riemannchow*:老周谈建筑。
版权声明:内容**网络,仅供学习和研究使用,版权归原作者所有。 如有侵权,请告知我们,我们将立即删除并道歉。 谢谢!