后端工程师的高阶面经
邓明
前 Shopee 高级工程师,Beego PMC
6888 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 50 讲
后端工程师的高阶面经
15
15
1.0x
00:00/00:00
登录|注册

18|分布式事务:如何同时保证分库分表、ACID和高性能?

面试思路
容错方案
容错
延迟事务
全开事务
容错
反向操作
容错
反向补偿
容错
TCC 与本地事务
Cancel
Confirm
Try
XA 与 ACID
优缺点
第三阶段(Commit)
第二阶段(PreCommit)
第一阶段(CanCommit)
缺点
提交阶段
准备阶段
思考题
总结
禁用跨库事务
延迟事务
AT 事务
SAGA 事务
TCC 事务
XA 事务
三阶段提交
两阶段提交
分布式事务

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

你好,我是大明。
我们在把单库拆分成为分库分表之后,一个巨大的挑战就是本地事务变成了分布式事务。事实上,即便没有分库分表,在微服务架构之下我们也还是会面临分布式事务的问题。所以,在学习了微服务架构又学习了分库分表之后,是时候深入讨论一下分布式事务了。
分布式事务在面试中是一把双刃剑,用得好,那么会是一个非常强的加分项。但是如果你基础不够扎实,见闻不够广博,面分布式事务很容易翻车,所以熟练掌握分布式事务很重要。
希望你学完这节课的内容之后可以自信地在简历里写上精通分布式事务这一条,提高简历通过筛选的几率,同时也在面试过程中刷出亮点,给面试官留下深刻印象。

前置知识

关于分布式事务,首先你需要弄清楚一个东西,就是分布式事务既可以是纯粹多个数据库实例之间的分布式事务,也可以是跨越不同中间件的业务层面上的分布式事务。前者一般是分库分表中间件提供支持,后者一般是独立的第三方中间件提供支持,比如 Seata。你在面试的时候,要根据上下文确定面试官问你的分布式事务是哪一类,然后有针对性地回答。
要学习分布式事务,我们要先学习分布式事务中几个比较常用的协议。

两阶段提交

两阶段提交协议(Two Phase Commit)是分布式事务中的一种常用协议,算法思路可以概括为参与者将操作成败通知协调者,再由协调者根据所有参与者的反馈情况决定各参与者要提交操作还是中止操作。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

分布式事务是分库分表或微服务架构中的挑战之一。本文介绍了分布式事务中常用的协议,包括两阶段提交、三阶段提交和XA事务。两阶段提交协议通过准备和提交阶段保证事务一致性和可靠性,但存在节点阻塞和单点故障等缺点。三阶段提交协议引入CanCommit阶段,减少了事务失败的可能性。XA事务是将两阶段提交协议具象化的标准。文章还提到了面试中可能涉及的问题和准备工作,包括跨库事务、分布式事务方案和数据一致性等。读者可以通过学习本文内容,了解分布式事务的常用协议和面试准备相关知识,提高对分布式事务的理解和应对能力。 TCC、AT和SAGA是追求最终一致性的分布式事务解决方案,分别强调业务自定义逻辑、反向补偿和生成数据库反向操作。容错和禁用跨库事务也是讨论的重点。文章还介绍了禁用跨库事务和延迟事务的解决方案,以及面试思路和技巧。总体而言,本文全面介绍了分布式事务的协议、解决方案和面试准备,对于从事分布式系统开发和面试准备的读者具有重要参考价值。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《后端工程师的高阶面经》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(11)

  • 最新
  • 精选
  • ZhiguoXue_IT
    业界内落地实用基本都是mq保证最终一致性,但是据说银行系统是强一致性,作者认为呢

    作者回复: 我持怀疑态度。我个人理解,分布式事务里面,如果事务协调者,事务参与者没有什么 redo 和 undo log 之类的东西,我个人认为它们不可能达成强一致性。但是问题又来了,事务协调者还要考虑 ACID 中的 AID 问题,不仅仅是一致性。举个例子,在意图保证强一致性的场景里面,你要不要考虑隔离性的问题?一个分布式事务能不能看到另外一个分布式事务的修改? 所以,综合来说,我持怀疑态度。之前听过一点银行的技术分享,他们说的强一致性其实都是最终一致性,总是有不一致的问题。也可能是我孤陋寡闻了。

    2023-07-26归属地:北京
    2
  • 锅菌鱼
    saga的反向补偿和AT的undolog是差不多的吧?

    作者回复: 我看起来是差不多,我觉得 AT 就是一种在 SQL 层面上的 SAGA。个人观点。

    2023-10-20归属地:广东
    1
  • 程序猿佬鸟
    老师您好: Q1: 延时事务在分库分表中间件中有实现吗? 您能具体说一个方向吗? 看完您这章我有点蒙圈了

    作者回复: 我以前写过的分库分表中间件就有这一个策略。开源的话,我记得 GO 中的 vitess 好像就是这么搞的。至于具体的分库分表的代理如 mycat 之类的,我就不太记得了。

    2024-01-28归属地:中国香港
  • Geek_3d0fe8
    那个TCC如果confirm失败了,为什么只能进行重试呢? 调 cancel 不行吗

    作者回复: 你可以调 cancel,但是问题在于,万一一部分人已经 confirm 成功了呢?

    2023-12-11归属地:广东
    2
  • sheep
    延迟事务有哪些中间件实现了呢?实际开发中要操作的话,我们该怎么操作

    作者回复: 基本上分库分表中间件都会实现吧,因为这是最简单的事务形态了。 实际中你就用装饰器,装饰不同 DB 的事务。然后当要执行操作的时候,你就看看有没有开事务,没有你就开事务,有了你就直接用已有的事务。

    2023-11-08归属地:广东
  • sheep
    老师这里有几个问题[嘿嘿] 问题1: TCC 另外一个方案中,进行丢掉这个数据,这里图片好像没有看到丢掉这个流程耶 问题2: AT事务下会帮你生成反向操作。有哪些分布式事务中间件支持这种反向操作呀 问题3: 业务A调用业务B,业务A根据业务B的执行情况来确定是继续执行,还是回滚,这种也属于分布式事务么 问题4:并发高的业务,分布式事务频繁失败情况下,会不会导致不一致的情况越来越严重?虽然有自动修复进行缓解。 其他的: “也就是把话题引导到延迟事务这个方案方案上”,是不是多了一个“方案”两个词 “只有db_2上开启的事务用上了”图片这里应该是db_1吧

    作者回复: 1. 虽然画了返回响应,但是不是说返回正确响应,而是返回一个异常响应。其实如果你是同步修复的话,你可以修复了之后返回正确顺序 2. 据我了解,seata 是支持的 3. 分布式事务这个词已经被用烂了,所以这里这么说也没错。 4. 如果分布式事务频繁失败,你关心的就不是数据一致性了,你要首先解决频繁失败的问题。正常来说,失败比率都是低于万分之一的。比如说以前我们一天百万的数据,不一致的数据也不到个位数。 db_2 的我没找到,感谢纠正。

    2023-11-08归属地:广东
  • Geek8004
    自动故障处理的机制不是很明白.针对这句话“修复数据本身分成两种,一种是用已经提交的数据库的数据来修复没有提交成功的数据库的数据;另外一种则是用没有提交成功的数据库的数据来还原已经提交的数据库的数据。 ”只有一份数据,假如我db1 rollback失败,此时db0之前已经提交了数据,我怎么用已提交的数据修复未提交的?他们数据没有冗余呀

    作者回复: 你这个场景我其实没有理解。就是如果 db0 是提交的话,那么 db1 也是提交,不会出现 db0 提交,db1 回顾的场景。 如果 db0 提交成功了,但是 db1 没有提交成功,那么就用 db0 的数据去修复 db1。

    2023-08-30归属地:中国香港
  • peter
    请教老师几个问题: Q1:根据文章内容,不管哪种分布式事务解决方案,都做不到ACID,都无法保证不出问题。那么,在实际的应用中,分布式事务的成功率一般能达到多少? Q2:AT是概念还是具体框架? Q3:单库但有分表,是否存在分布式事务? Q4:两个SQL可以共用一个事务,前提是这两个SQL是属于一个Session吗?不同Session的SQL不能共用一个事务吧。 Q5:对数据库进行修复会影响业务吗?如果会影响,会采取哪些措施?

    作者回复: 1. 这个要看业务。成功率是一个不够准确的定义,你应该说取得一致性的时间是多长,以及没有办法达成一致的比率有多高。实际上,你应该做到和你的可用性一致。比如说正常,我们都会要求最终不一致的数据,每天应该控制在个位数。太多了你手工修复很要命的。 2. 我个人认为,是 seata 里面引入的。我比较孤陋寡闻,没见着别的地方哟用。我自己理解的话喜欢把它说成是 SAGA 的自动化的特殊形态。 3. 嘿嘿,如果你的分库分表中间件做得好,那么就没有。有些分库分表中间件是语句维度来调度的,所以搞不好也引入了分布式事务。 4. 对的 5. 主要是小心并发。比如说你数据出错了,你准备去修复。但是你修复之前,可能另外一个请求又把错误的数据更新为新数据了,但是这个新数据是对的。所以最好是在修复的时候要根据更新时间、版本号之类的来判断一下,避免出现并发覆盖的问题。

    2023-07-27归属地:北京
  • 进击的和和
    老师你好 协调者让参与者执行事务,但是并不提交,协调者返回执行情况 这里是不是参与者返回执行情况呢。 我在两阶段提交那里说到在提交阶段,协调者会不断重试直到把 Commit 请求发送给协调者;协调者如果在提交阶段中途崩溃,也要确定是否需要提交或者回滚。那么你就应该可以理解,在重试成功之前,或者在协调者恢复过来重新提交或者回滚之前,数据是不一致的。这句话好像有点小问题吧。 两阶段提交如果a参与者成功了,b参与者失败了,那么是不是只能人工处理或者有个修复数据的脚步进行修复呢? 关于容错,如果协调者挂了,那么参与者1是否可以询问其他参与者情况呢

    作者回复: 1. 是参与者返回执行情况。 2. b 参与者如果在准备阶段就失败了,那么直接回滚,这个应该没什么疑问。问题是在 commit 阶段,如果 b 参与者 commit 失败了怎么办。那么按照两阶段提交协议的要求,b 参与者这时候是不能 commit 失败的,b 要不断重试,或者用别的手段保证自己的成功。但是,显然这也是一个不现实的要求,所以 b commit 最终失败之后,肯定要人工介入的。这你也可以看出来,又出现了不一致。从理论上来说,协调者在发现 b 死活不能提交成功之后,那么 a 提交的数据应该也要处于一种不可用的状态,可惜的是,我们也做不到。 3. 参与者可以考虑询问。但是这里有一个问题,就是你问几个人呢?比如说十个节点里面,你问了六个人,三个人告诉你提交,三个人告诉你不知道,这时候你是提交还是不提交?那三个不知道的,又该怎么办?所以整体这需要一个比较复杂的机制。

    2023-07-26归属地:四川
  • 程序猿佬鸟
    延迟事务?sharding JDBC也没有实现啊
    2024-01-28归属地:中国香港
收起评论
显示
设置
留言
11
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部