Java性能调优实战
刘超
金山软件西山居技术经理
立即订阅
7535 人已学习
课程目录
已完结 48 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | 怎样才能做好性能调优?
免费
模块一 · 概述 (2讲)
01 | 如何制定性能调优标准?
02 | 如何制定性能调优策略?
模块二 · Java编程性能调优 (10讲)
03 | 字符串性能优化不容小觑,百M内存轻松存储几十G数据
04 | 慎重使用正则表达式
05 | ArrayList还是LinkedList?使用不当性能差千倍
加餐 | 推荐几款常用的性能测试工具
06 | Stream如何提高遍历集合效率?
07 | 深入浅出HashMap的设计与优化
08 | 网络通信优化之I/O模型:如何解决高并发下I/O瓶颈?
09 | 网络通信优化之序列化:避免使用Java序列化
10 | 网络通信优化之通信协议:如何优化RPC网络通信?
11 | 答疑课堂:深入了解NIO的优化实现原理
模块三 · 多线程性能调优 (10讲)
12 | 多线程之锁优化(上):深入了解Synchronized同步锁的优化方法
13 | 多线程之锁优化(中):深入了解Lock同步锁的优化方法
14 | 多线程之锁优化(下):使用乐观锁优化并行操作
15 | 多线程调优(上):哪些操作导致了上下文切换?
16 | 多线程调优(下):如何优化多线程上下文切换?
17 | 并发容器的使用:识别不同场景下最优容器
18 | 如何设置线程池大小?
19 | 如何用协程来优化多线程业务?
20 | 答疑课堂:模块三热点问题解答
加餐 | 什么是数据的强、弱一致性?
模块四 · JVM性能监测及调优 (6讲)
21 | 磨刀不误砍柴工:欲知JVM调优先了解JVM内存模型
22 | 深入JVM即时编译器JIT,优化Java编译
23 | 如何优化垃圾回收机制?
24 | 如何优化JVM内存分配?
25 | 内存持续上升,我该如何排查问题?
26 | 答疑课堂:模块四热点问题解答
模块五 · 设计模式调优 (6讲)
27 | 单例模式:如何创建单一对象优化系统性能?
28 | 原型模式与享元模式:提升系统性能的利器
29 | 如何使用设计模式优化并发编程?
30 | 生产者消费者模式:电商库存设计优化
31 | 装饰器模式:如何优化电商系统中复杂的商品价格策略?
32 | 答疑课堂:模块五思考题集锦
模块六 · 数据库性能调优 (8讲)
33 | MySQL调优之SQL语句:如何写出高性能SQL语句?
34 | MySQL调优之事务:高并发场景下的数据库事务调优
35 | MySQL调优之索引:索引的失效与优化
36 | 记一次线上SQL死锁事故:如何避免死锁?
37 | 什么时候需要分表分库?
38 | 电商系统表设计优化案例分析
39 | 数据库参数设置优化,失之毫厘差之千里
40 | 答疑课堂:MySQL中InnoDB的知识点串讲
模块七 · 实战演练场 (4讲)
41 | 如何设计更优的分布式锁?
42 | 电商系统的分布式事务调优
43 | 如何使用缓存优化系统性能?
44 | 记一次双十一抢购性能瓶颈调优
结束语 (1讲)
结束语 | 栉风沐雨,砥砺前行!
Java性能调优实战
登录|注册

42 | 电商系统的分布式事务调优

刘超 2019-08-27
你好,我是刘超。
今天的分享也是从案例开始。我们团队曾经遇到过一个非常严重的线上事故,在一次 DBA 完成单台数据库线上补丁后,系统偶尔会出现异常报警,我们的开发工程师很快就定位到了数据库异常问题。
具体情况是这样的,当玩家购买道具之后,扣除通宝时出现了异常。这种异常在正常情况下发生之后,应该是整个购买操作都需要撤销,然而这次异常的严重性就是在于玩家购买道具成功后,没有扣除通宝。
究其原因是由于购买的道具更新的是游戏数据库,而通宝是在用户账户中心数据库,在一次购买道具时,存在同时操作两个数据库的情况,属于一种分布式事务。而我们的工程师在完成玩家获得道具和扣除余额的操作时,没有做到事务的一致性,即在扣除通宝失败时,应该回滚已经购买的游戏道具。
从这个案例中,我想你应该意识到了分布式事务的重要性。
如今,大部分公司的服务基本都实现了微服务化,首先是业务需求,为了解耦业务;其次是为了减少业务与业务之间的相互影响。
电商系统亦是如此,大部分公司的电商系统都是分为了不同服务模块,例如商品模块、订单模块、库存模块等等。事实上,分解服务是一把双刃剑,可以带来一些开发、性能以及运维上的优势,但同时也会增加业务开发的逻辑复杂度。其中最为突出的就是分布式事务了。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《Java性能调优实战》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(22)

  • G
    目前主流的做法不是通过异步消息来实现的吗。下单同步调用扣减库存接口。然后业务线监听订单状态接口实现业务。对于扣减库存如果发生超时,下单失败。商品中心监听费单消息,加回库存。来实现最终一致性。其他业务类同

    作者回复: MQ实现的分布式事务也是TCC的一种实现方式,也是主流的一种分布式解决方案

    2019-09-18
    3
  • QQ怪
    不太理解seata默认隔离级别为啥是未提交读,不怕脏读?还是为了保证性能才做的妥协?

    作者回复: 默认情况下,seata认为大多数分布式业务涉及到脏读的可能性比较小,所以保证了大多数场景下的高效性。

    如果需要达到全局的 读已提交,seata也提供了相应的机制来达到目的。

    2019-08-28
    2
  • 任鹏斌
    老师有个问题阿里的开源分布式方案是事务管理器是单点的,如果挂掉了会不会引起事务不一致?

    作者回复: 会的,我在文中已经提到了

    2019-09-03
    1
  • -W.LI-
    老师好!
    Seata 设计通过事务协调器维护的全局写排它锁,来保证事务间的写隔离,而读写隔离级别则默认为未提交读的隔离级别。
    这个全局写排他锁支持那几种锁啊?
    行锁,表锁,间隙锁,元数据锁别的记不起来了
    如果支持的锁粒度不够吞吐量也会降低很多吧。

    作者回复: 赞,全局写排它锁是根据resourceId + table + pks实现。

    2019-08-27
    1
    1
  • -W.LI-
    课后习题:全局写锁,第一阶段没有准确的提交或者回滚前,后续业务无法持有锁。我本来还想问下老师这个是怎么做到的,不过老师最后写了嘿嘿省的问了。默认读为提交,不怕脏读么?
    TCC协议具体每一步怎么做讲一下么老师?
    已订单支付为例,
    try:尝试预扣处理,怎么预扣呢。用redis锁库存还是直接怎么锁。(抢购装备,游戏币和装备都在try阶段锁定。冲突大的后try,提交的时候冲突大的先commit?)。
    try阶段,如果同时有多个事务进行try操作都能try成功么?如果支持try成功感觉有可能出现课后问题的情况。try这一步很重要啊,需要保证try以后,一定能提交成功,也一定能回滚。会不会有万一的?万一兜底解决是人工处理么?

    作者回复: 对的,我们首先要使用重试机制,其次保证记录日志。

    2019-08-27
    1
  • neohope
    老师您好,是不是可以这样理解,Seata是通过TM管理全局事务,所有用Seata的AP都可以实现写的隔离,也就是对同一行数据有影响的时候,并不存在分布的A事务没有操作完毕,B事务就开始操作的情况。

    Seata默认采用了很乐观的分布式策略,CAP里面优先保证了A,并没有彻底解决脏读的问题。

    而如果设置为读“已提交”,那就要Seata在内存记录额外的数据,用于返回已提交的"正确数据"?而这个就又扯出内存管理或崩溃时这些"正确数据"持久化的问题,导致系统复杂度上升?这样理解对吗?

    作者回复: 是的

    2019-11-26
  • seustones
    思考题:seata是行锁,所以别的线程无法更新该记录,即便是回滚也是不会出现脏数据的,最多出现脏读,但是可以设置全局事务隔离级别为读已提交,不过绝大多数场景下读未提交已满足需求
    2019-11-08
  • 天涯xj
    为什么JTA不能适合单一数据源的分布式事务?

    作者回复: 适用,不同的分布式事务各有自己的优缺点,可以根据自己的需求来选择最适合自己的分布式事务的实现方式。

    2019-10-30
  • Demon.Lee
    TCC 也是基于二阶事务提交原理实现的,但 TCC 的二阶事务提交是提到了服务层实现。
    Seata将RM也提升到了服务层实现。
    --------老师,这两种服务层实现,应该不是一回事吧

    作者回复: 是的,seata的RM提升到了服务层

    2019-09-22
  • Gred
    思考题:为什么SeaTac不会产生脏数据,第一点因为全局排它锁,全局排它锁的结构是【resourceId + table + pks】,精确到某个资源某张表的某个条数据。第二点,如果A事务对于【Select * from table where id = pks for update】数据执行失败,且未回滚【resourceId+table+pk】,这时全局锁尚未释放。B事务申请相同资源的全局锁会失败。该条数据只能看不能处理,也说不上产生脏数据了。
    2019-09-18
  • 再续啸傲
    文中“如果 RM 决议要全局回滚,会通知 RM 进行回滚操作”,按照学习后的理解,应该是TC决定是否要进行全局回滚,不知道我理解的是否有偏差,忘老师指正

    作者回复: 对的,已修正

    2019-09-04
  • Jxin
    1.第一次听到TCC,感觉也是两阶段提交的思想,只是把询问变成try操作。
    2.至于补偿,感觉mq的方式更像是在补偿。(在这里,因为mq是最终一致所以个人觉得更像补偿)
    3.分布式事务框架还有个lcn,事务的搬运工。
    2019-09-04
  • N
    老师您好,微服务间在事务中通过dubbo调用的方式是不是也可以实现分布式事务?

    作者回复: 可以的,Seata中有个基于dubbo实现的分布式事务的例子,有兴趣可以自己参考手动实践一下

    2019-09-01
  • 灿烂明天
    老师好,我看网上有些是用mq消息中间件来解决分布式事务的,其实这个方案能不能解决分布式事务问题的?他的思想是基于tcc的吗?

    作者回复: 可以的,目前很多团队用过MQ实现分布式事务,也是基于TCC的思想实现。

    2019-08-28
  • 许童童
    分页式事务中常用的方法:
    1.二阶段提交
    2.三阶段提交
    3.TCC事务
    4.Seata(有待验证)
    2019-08-27
  • 晓杰
    全局写锁,如果线程还没有提交或者回滚事务,其他线程无法获得锁
    老师,默认的隔离级别是读未提交,不是会发生脏读吗,这里是不是有问题

    作者回复: 默认情况下,seata认为大多数分布式业务涉及到脏读的可能性比较小,所以保证了大多数场景下的高效性。

    2019-08-27
  • 疯狂咸鱼
    老师,会讲Paxos算法么,面试经常会问道

    作者回复: 可以考虑加餐

    2019-08-27
  • 疯狂咸鱼
    老师是全能!
    2019-08-27
  • JackJin
    seata一阶段提交拿 全局锁 尝试被限制在一定范围内,超出范围将放弃,并回滚本地事务,释放本地锁。
    这句话不理解,麻烦老师解答一下!

    作者回复: 这句话在哪看到的呢,没有太理解。seata是根据一个全局事务ID进行上下文传播的。

    2019-08-27
    1
  • JackJin
    一阶段本地事务提交前,需要确保先拿到 全局锁 。
    拿不到 全局锁 ,不能提交本地事务。
    拿 全局锁 的尝试被限制在一定范围内,超出范围将放弃,并回滚本地事务,释放本地锁。
    以一个示例来说明:

    两个全局事务 tx1 和 tx2,分别对 a 表的 m 字段进行更新操作,m 的初始值 1000。

    tx1 先开始,开启本地事务,拿到本地锁,更新操作 m = 1000 - 100 = 900。本地事务提交前,先拿到该记录的 全局锁 ,本地提交释放本地锁。 tx2 后开始,开启本地事务,拿到本地锁,更新操作 m = 900 - 100 = 800。本地事务提交前,尝试拿该记录的 全局锁 ,tx1 全局提交前,该记录的全局锁被 tx1 持有,tx2 需要重试等待 全局锁 。
    2019-08-27
收起评论
22
返回
顶部