Java 性能调优实战
刘超
前金山软件技术经理
59174 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 49 讲
开篇词 (1讲)
模块一 · 概述 (2讲)
结束语 (1讲)
Java 性能调优实战
15
15
1.0x
00:00/00:00
登录|注册

41 | 如何设计更优的分布式锁?

实现方式和可靠性比较
性能比较
Redlock算法
Lua脚本实现
SETNX增加过期时间参数
SETNX+EXPIRE组合
实现方式
Watch机制
顺序临时节点
性能瓶颈
校验订单幂等性
创建锁表
避免分布式中的不同节点执行重复性的工作
保证共享资源的原子性
分布式环境下的Java锁失效
JVM中的同步锁和Lock锁
Redisson实现的分布式锁是否一定不会出现同时获得锁的可能
总结
Redis实现分布式锁
Zookeeper实现分布式锁
数据库实现分布式锁
用途
问题
思考题
分布式锁
如何设计更优的分布式锁?

该思维导图由 AI 生成,仅供参考

你好,我是刘超。
从这一讲开始,我们就正式进入最后一个模块的学习了,综合性实战的内容来自我亲身经历过的一些案例,其中用到的知识点会相对综合,现在是时候跟我一起调动下前面所学了!
去年双十一,我们的游戏商城也搞了一波活动,那时候我就发现在数据库操作日志中,出现最多的一个异常就是 Interrupted Exception 了,几乎所有的异常都是来自一个校验订单幂等性的 SQL。
因为校验订单幂等性是提交订单业务中第一个操作数据库的,所以幂等性校验也就承受了比较大的请求量,再加上我们还是基于一个数据库表来实现幂等性校验的,所以出现了一些请求事务超时,事务被中断的情况。其实基于数据库实现的幂等性校验就是一种分布式锁的实现。
那什么是分布式锁呢,它又是用来解决哪些问题的呢?
在 JVM 中,在多线程并发的情况下,我们可以使用同步锁或 Lock 锁,保证在同一时间内,只能有一个线程修改共享变量或执行代码块。但现在我们的服务基本都是基于分布式集群来实现部署的,对于一些共享资源,例如我们之前讨论过的库存,在分布式环境下使用 Java 锁的方式就失去作用了。
这时,我们就需要实现分布式锁来保证共享资源的原子性。除此之外,分布式锁也经常用来避免分布式中的不同节点执行重复性的工作,例如一个定时发短信的任务,在分布式集群中,我们只需要保证一个服务节点发送短信即可,一定要避免多个节点重复发送短信给同一个用户。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
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-24
    2
    27
  • 风轻扬
    老师,zk实现的锁,不会出现redis锁一样的问题吗? 设想: 应用1和应用2两个服务分别部署到不同的服务器上。是使用zookeeper实现分布式锁。应用1获取到锁,然后开始长时间gc,应用2也开始长时间gc。应用1的zk锁由于心跳超时释放了锁,应用2结束gc获取到锁,应用1结束gc开始执行任务,此时不就有两个任务在同时执行了吗?

    作者回复: 是的,这种情况也同样存在同时获取锁的可能

    2019-09-25
    3
    17
  • 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-24
    2
    9
  • Geek_cecf23
    老师,之前你讲过一节 36节,记一次线上SQL死锁事故,for update 使用会导致死锁问题,直接使用for update 实现分布式锁,不也会暗含了死锁的可能么

    作者回复: 是的,当在RR事务级别下,在数据库中不存在当前key值的情况下,多线程竞争锁会因为意向锁的问题,导致死锁。可降低数据库隔离级别为 Read Commited,这样的话多个事务不会因为意向锁的原因导致死锁了。

    2020-04-27
    8
  • neohope
    老师您好,我有两个问题: redisson会向所有的redis节点并发发起请求,获取一半以上的锁才会进行后续操作。那我的疑问是, 1、这样不会让整体性能变得比redis集群要差一些吗?而且redis节点越多,redisson性能越差? 2、redisson的客户端,如果无法获取到足够多redis节点的锁,其释放规则及防止冲突的规则又是如何处理的呢?如果没有合理的防冲突规则,感觉并发量越高,性能会越差。

    作者回复: 鱼和熊掌不可兼得,保证可靠性的前提下,会带来一定的性能损失。 当在一定时间内没有获取到足够节点时,会通过定时任务将已经超时的锁通过lua脚本来释放。

    2019-11-26
    2
    3
  • 风轻扬
    老师,互联网行业,多数都是redis集群啊,如果这样,基于redis实现的分布式锁是不是就不能用了?

    作者回复: 可以,使用Redisson就好了

    2019-09-24
    3
  • rrbbt
    老师,使用select for update防止幻读那里,直接把order_no设置成唯一索引,事务里面只有一条insert语句就可以吧?如果之前有,插入不成功,没有的话,插入成功

    作者回复: 是的,唯一索引可以实现该功能。

    2019-08-27
    3
  • 桔子
    redisson分布式锁解决单实例或多个完全互相独立master节点分布式环境获取锁的问题。但是主从或cluster集群下,异步通信导致获取锁多次获取的问题并没解决,理解对否?

    作者回复: 对的

    2020-04-08
    2
  • 知行合一
    老师,想问个问题,redis集群已经分了槽,客户端写入根据算法应该写入一个节点啊,为啥要多个节点同时枷锁?

    作者回复: 写入一个单点只实现了高可用,没有实现集群式分布式锁。单点的问题会存在单个节点挂了的情况下,不同应用服务同时获取锁的可能。

    2019-09-05
    5
    2
  • 我已经设置了昵称
    不太懂redission机制,每个节点各自去获取锁。超过一半以上获取成功就算成功。那是不是还有这么一步:这些一半以上的机器获取了以后,是否还要决定谁真正拿到锁,才能真正执行这个任务

    作者回复: 都会设置锁对象

    2019-08-25
    2
收起评论
显示
设置
留言
45
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部