37|分布式锁:如何保证Redis分布式锁的高可用和高性能?
能用于实现分布式锁的中间件
面试准备
- 深入了解
- 翻译
- 解释
- 总结
分布式锁是分布式系统中的重要话题,本文深入介绍了如何使用Redis实现高可用和高性能的分布式锁。文章首先介绍了分布式锁的基本概念和在面试中的热度,然后详细讨论了使用Redis的SETNX命令实现加锁和DEL命令实现释放锁的过程,以及加锁失败时的等待时间、实现等待机制和加锁重试的方法。此外,文章还提到了分布式锁需要设置合适的过期时间,并介绍了续约机制和中断业务的处理方法。另外,文章还提到了Redlock算法以及性能优化的方案。总的来说,本文对分布式锁的实现原理和相关技术细节进行了深入浅出的介绍,对于想要深入了解分布式锁的读者具有很高的参考价值。 文章还提到了性能优化的思路,包括优化Redis性能和减少分布式锁的竞争,以及去除分布式锁的场景和思路。此外,还提出了面试思路总结和思考题,为读者提供了更多的思考和讨论空间。 总的来说,本文内容丰富,涵盖了分布式锁的实现原理、性能优化、去除分布式锁的场景和思路等多个方面,对于想要深入了解分布式锁的读者具有很高的参考价值。
《后端工程师的高阶面经》,新⼈⾸单¥59
全部留言(6)
- 最新
- 精选
- Geek_84f004老师您好,Singleflight模式多次提到了,但如何实现这个模式,老师有比较好的建议吗?比较害怕的是在这个模式下可能有太多的线程处于等待状态?是否有隐患
作者回复: 在 GO 里面自带了,JAVA 里面也有开源的实现,其它语言就不清楚了。不过总的来说,还是一个比较复杂的事情,对并发要求比较高。 有隐患,隐患就是你真的去执行的线程执行了很长时间。所以你可以考虑一个结合了超时机制的 singleflight(大部分开源实现不支持)。而别的线程等待超时了,也有两个选择:1. 不再等,直接返回;2. 自己直接去取。 目前我倒是还没遇到过线上因为 singleflight 导致线程长时间阻塞的问题。 归根结底,还是得确保业务要能短时间结束。
2023-09-13归属地:浙江1 - 冲冲冲redLock 加锁多数原则 ,5台机器为啥加锁4个成功,有一个超时失败要把其他四个解锁尼,不是已经超过半数了吗
作者回复: 我后面释放锁的那里,是指执行业务之后,释放锁的时候不要忘了释放这个超时的节点上的锁。
2023-10-23归属地:江苏 - 文敦复Singleflight 模式 来优化竞争,感觉需要处理很多复杂问题:选择哪个线程去竞争?获取锁过程中,如果这个线程奔溃,如何通知其他线程?获取锁过程中,其他线程如何自处(直接失败?等待失败? 等待成为竞争者?) 感觉不玩这个奇技淫巧,大开大合,以力破巧更实在,要不然被面试官绕进去,那就尴尬啦...
作者回复: 哈哈哈,这个在 Go 里面倒是不需要我们烦恼,因为 Go 自身就提供了一个 singleflight。 我个人觉得线程崩溃倒是不太需要考虑,一般来说线程崩溃,都是整个应用崩溃了。就 singleflght 的“标准实现”来说,其他线程都是等待。而使用者可以决定在等待之后,要不要继续尝试新一轮。
2023-10-11归属地:四川 - 文敦复请教下:“如果 key1 存在,检查值是不是 value1。如果是 value1,那么说明我上一次加锁成功了。考虑到距离重试的时候已经过去了一段时间,所以需要重置一下过期时间。” 如果 key1 都存在了,不就代表上资源被占用了吗,这次加锁应该算失败吧,还继续操作干嘛?
作者回复: 因为 key1 的值是 value1,也就是你当时加锁成功了(value1是你生成的,且是唯一的,比如说是 uuid),只不过你很不幸拿到了超时响应。
2023-10-11归属地:四川 - peter请教老师几个问题: Q1:线程1设置key1=value1,线程2设置key1=value2能成功吗? 键相同,都是key1,但值不同,可以设置吗? Q2:订阅键值对,是Redis已经具备的功能吗?还是需要进一步开发? Q3:释放锁的时候,线程1为什么能把线程2的锁释放掉?两个锁应该是不同的锁啊。 Q4:释放锁的时候,比较value,是谁比较?Redis比较吗?
作者回复: 1. 如果你不用 NX 命令的话,是可以成功的 2. 已经有了,你可以了解一下 Redis 的订阅功能 3. 对同一个 key 加的分布式锁 4. 就是和 redis 里面存储的值比较
2023-09-13归属地:北京 - sheep课后问题: 1. 重试时候,要考虑重试次数还有重试间隔 2. 有一个分布式锁无效的情况,就是异地部署情况下,两个服务使用的都是自己的redis,这时候使用redis分布式锁无效(因为两个服务没有连到同一个redis中间件么), 但存在只允许一个服务进行执行指定业务的场景。这里有两个服务,B服务(备用业务服)连的数据库是作为A服务(主业务服)连的数据库的备用数据库,数据库MySQL主备数据之间是有进行同步。因此这里做了一个比较简易的方案,就是A服务和B服务定时执行一个业务时,A服务往一个业务执行表(tbl_lock_record)插入一条数据,B服务要执行时,延迟1~2s(考虑到主备数据库延时问题),然后先判断tbl_lock_record表内指定时间范围有没有执行过的数据( 当前时间-定时时长-延迟时长< time <= 当前时间),若有则B服务不进行执行定时任务。 同样,这种方法也存在挺多问题: (1)时间判断不准确情况下,可能两个服务都会执行 (2)若主备数据同步失败(例如延迟时长内数据还未同步),B服务也会进行执行2024-02-19归属地:广东