41 | 如何设计更优的分布式锁?
该思维导图由 AI 生成,仅供参考
- 深入了解
- 翻译
- 解释
- 总结
分布式锁是解决分布式环境下共享资源访问的重要问题。本文从数据库实现和Zookeeper实现两个角度介绍了分布式锁的设计。作者首先介绍了基于数据库实现分布式锁的方法,通过创建锁表和使用事务来保证原子性,但存在性能瓶颈和复杂度增加的问题。其次,作者介绍了基于Zookeeper实现分布式锁的方式,利用Zookeeper的顺序临时节点和Watch机制来实现严格按顺序访问的并发锁。相比数据库实现,Zookeeper实现具有集群化、自动释放锁等优点,但也存在压力大和性能差的问题。 此外,文章还介绍了基于Redis实现的分布式锁,通过SETNX+EXPIRE组合实现,但存在死锁和性能问题。随后,文章提到了Redisson中的Redlock算法,通过在不同节点上获取锁的方式和超时机制来避免多个应用同时获得锁的问题。 总的来说,本文通过实际案例和技术原理,全面介绍了分布式锁的设计和实现方式,包括基于数据库、Zookeeper和Redis的实现方式,以及Redisson中的Redlock算法。读者可以从中了解到不同实现方式的优缺点,以及在不同场景下的推荐使用情况。 文章还提出了思考题,引发读者对Redisson实现的分布式锁是否一定不会出现同时获得锁的可能的讨论,为读者提供了进一步思考的空间。 总的来说,本文内容丰富,涵盖了分布式锁的多种实现方式和技术细节,适合对分布式系统感兴趣的读者阅读。
《Java 性能调优实战》,新⼈⾸单¥59
全部留言(45)
- 最新
- 精选
- -W.LI-老师好!基于数据库的实现,我现在项目中直接不开事务,select后插入(oeder_no做唯一约束)。try_catch 异常,重试3次。如果查到了返回成功保证密等。这么做会有问题么? 课后题:万一收到的N/2+1节点全部挂了肯定会有问题。不知道,从新选为master节点的算法不知,如果会选择没有收到的节点做master也会有问题。
作者回复: 没有问题。 问题的答案:redis实现的分布式锁,都是有一个过期时间,如果一旦服务A出现stop the world的情况,有可能锁过期了,而此时服务A中仍然存在持有锁,此时另外一个服务B又获取了锁,这个时候存在两个服务同时获取锁的可能。
2019-08-24227 - 风轻扬老师,zk实现的锁,不会出现redis锁一样的问题吗? 设想: 应用1和应用2两个服务分别部署到不同的服务器上。是使用zookeeper实现分布式锁。应用1获取到锁,然后开始长时间gc,应用2也开始长时间gc。应用1的zk锁由于心跳超时释放了锁,应用2结束gc获取到锁,应用1结束gc开始执行任务,此时不就有两个任务在同时执行了吗?
作者回复: 是的,这种情况也同样存在同时获取锁的可能
2019-09-25317 - a、不一定,因为如果集群中有5个redis,abcde,如果发生网络分区,abc在一个分区,de在一个分区,客户端A向abc申请锁成功,在c节点master异步同步slave的时候,master宕机了,slave接替,然后c的slave又和de在一个分区里,这时候如果客户端B来申请锁,也就可以成功了。 zk锁也会出现问题,如果客户端A申请zk锁成功,这时候客户端A和zk不在一个分区里,zk就会把临时节点删除,然后如果客户端B再去申请,也就可以申请成功
作者回复: 对的,这种情况也是可能发生的,前提是c节点在宕机之前没有持久化锁。 第二zk锁的问题,如果连接session已经断开,客户端的锁是会释放的,不会存在同时获取锁的情况。
2019-08-2429 - Geek_cecf23老师,之前你讲过一节 36节,记一次线上SQL死锁事故,for update 使用会导致死锁问题,直接使用for update 实现分布式锁,不也会暗含了死锁的可能么
作者回复: 是的,当在RR事务级别下,在数据库中不存在当前key值的情况下,多线程竞争锁会因为意向锁的问题,导致死锁。可降低数据库隔离级别为 Read Commited,这样的话多个事务不会因为意向锁的原因导致死锁了。
2020-04-278 - neohope老师您好,我有两个问题: redisson会向所有的redis节点并发发起请求,获取一半以上的锁才会进行后续操作。那我的疑问是, 1、这样不会让整体性能变得比redis集群要差一些吗?而且redis节点越多,redisson性能越差? 2、redisson的客户端,如果无法获取到足够多redis节点的锁,其释放规则及防止冲突的规则又是如何处理的呢?如果没有合理的防冲突规则,感觉并发量越高,性能会越差。
作者回复: 鱼和熊掌不可兼得,保证可靠性的前提下,会带来一定的性能损失。 当在一定时间内没有获取到足够节点时,会通过定时任务将已经超时的锁通过lua脚本来释放。
2019-11-2623 - 风轻扬老师,互联网行业,多数都是redis集群啊,如果这样,基于redis实现的分布式锁是不是就不能用了?
作者回复: 可以,使用Redisson就好了
2019-09-243 - rrbbt老师,使用select for update防止幻读那里,直接把order_no设置成唯一索引,事务里面只有一条insert语句就可以吧?如果之前有,插入不成功,没有的话,插入成功
作者回复: 是的,唯一索引可以实现该功能。
2019-08-273 - 桔子redisson分布式锁解决单实例或多个完全互相独立master节点分布式环境获取锁的问题。但是主从或cluster集群下,异步通信导致获取锁多次获取的问题并没解决,理解对否?
作者回复: 对的
2020-04-082 - 知行合一老师,想问个问题,redis集群已经分了槽,客户端写入根据算法应该写入一个节点啊,为啥要多个节点同时枷锁?
作者回复: 写入一个单点只实现了高可用,没有实现集群式分布式锁。单点的问题会存在单个节点挂了的情况下,不同应用服务同时获取锁的可能。
2019-09-0552 - 我已经设置了昵称不太懂redission机制,每个节点各自去获取锁。超过一半以上获取成功就算成功。那是不是还有这么一步:这些一半以上的机器获取了以后,是否还要决定谁真正拿到锁,才能真正执行这个任务
作者回复: 都会设置锁对象
2019-08-252