2024年常用的 分布式事务 都有哪些?我该用哪个?,年薪超过80万

最后

面试题文档来啦,内容很多,485页!

由于笔记的内容太多,没办法全部展示出来,下面只截取部分内容展示。

1111道Java工程师必问面试题

MyBatis 27题 + ZooKeeper 25题 + Dubbo 30题:

Elasticsearch 24 题 +Memcached + Redis 40题:

Spring 26 题+ 微服务 27题+ Linux 45题:

Java面试题合集:

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

这个投票比较有意思,只要有一个参与者返回了 false,本次事务就需要终止,然后执行 rollback。只有全票通过,才会正常 commit。协调者将这个结果,周知所有参与者的这个过程,就是二阶段。

二阶段提交其实非常容易理解。你可以把每个参与者的执行,想象成正常的 SQL 更新语句。它们一直挂在那里等待,直到协调者给出确切的 commit 或者 rollback 消息,才会正常往下执行。

2.3 问题

  1. 阻塞问题。两阶段提交最大的问题,就是它是一个阻塞的协议,效率低。如果协调器永久失败,一些参与者,将永远无法完成它的事务

  2. 单点故障问题。由于协调者在整个环节中有着非常重要的作用,所以一旦它发生了SPOF,整个系统将变的不可用,这是不能忍受的

  3. 事务完整性问题。在某些情况下,比如协调者发送 commit 指令后,发生异常,有一部分执行成功了,会造成整个事务不一致。因为能不能提交,第一阶段就决定了,第二阶段只是通知而已,你就是死也要给我提交

  4. 并不是所有的资源都支持 2PC(或者 XA)

对于第三点,我们举个例子。比如你的 commit-request 阶段全部返回了 yes,然后协调者发送了 commit 指令。但这时候,有一台服务器 A 宕机了,无法执行这个 commit。这时候,我们的 client 也会收到成功的消息。A 机器重启之后,要有能力来恢复、继续执行 commit 指令,这些都是工程上必须要处理的。

2.4 框架

2PC 也叫做 XA 事务,大多数数据库如 MySQL,都支持 XA 协议。在 Java 中,JTA(不是什么 JPA 哦)是 XA 协议的实现。Spring 也有 JTA 的事务管理器。

  • Atomikos、bitronix 实现了 JTA,它们只需要提供 jar 包就可以了。实现了 XA 协议的数据库或者消息队列,已经能够具备了准备、提交、回滚的各种能力

  • 使用在 seata 等框架,需要启动一个独立的 seata 服务协调者节点。seata 使用的 AT,借助于外部事务管理器,概念与 XA 类似

3. 三阶段提交(3PC)


相比较二阶段提交,三阶段提交最典型的特点是加入了超时机制。当然,3 阶段证明了它有三个阶段,这个差别更显著。它本质上只是 2PC 的一些改进,所以身上完全充满了 2PC 的影子。

3.1 重要参与者

3PC 和 2PC 是一样的。

3.2 过程

3PC 比 2PC 多了一个步骤,那就是询问阶段。

  1. CanCommit 询问阶段

  2. PreCommit 准备阶段

  3. DoCommit 提交阶段

提交阶段,无非就是发送个 commit 或者 rollback 指令,重要的处理还是在准备阶段,3PC 把它一拆为 2。

注意下面这个对应关系哦,2PC 和 3PC 都有一个准备阶段,但它们的作用是不同的。

3PC 2PCCanCommit commit-request/votingPreCommit DoCommit commit``复制代码

复制代码

3PC 的询问阶段,对应的才是 2PC 的准备阶段,都是 ask 一下参与者是否准备好了,但执行过程会有一些区别。

为什么要这么做?因为 2PC 有效率问题。2PC 的执行过程是阻塞的,一个资源在进入准备阶段之后,必须等待所有的资源准备完毕才能进行下一步,在这个过程中,它们对全局一无所知。

比如,有 ABCDE 等 5 个参与者,E 其实是一个有问题的参与者资源。但 2PC 每次都会执行 ABCD 的预提交,当询问到 E 的时候,发现是有问题的,再依次执行 ABCD 等参与者的 rollback。在这种情况下,ABCD 执行了无用的事务预处理和 rollback,是非常浪费资源的。

3PC 通过拆分这个询问阶段,在确保所有参与者建康良好的情况下,才会发起真正的事务处理,在效率和容错性上更胜一筹。从概率上来讲,由于 commit 之前粒度变小了,commit 阶段出问题的几率就变小,能省下不少事。

另外,3PC 引入了超时机制。在 PreCommit 阶段,如果超时,就认为失败;而在 DoCommit 阶段,如果超时还会继续执行下去。但不论怎样,整个事务并不会一直等待下去。

3.3 问题

3PC 理论上是比较优秀的,还能够避免阻塞问题,但它多了一次网络通信。如果参与者的数量比较多,网络质量比较差的情况下,这个开销非常可观。它的实现也比较复杂,在实际应用中,是不太多的。

3PC 也并不是完美的,因为 PreCommit 阶段和 DoCommit 也并不是原子的,和 2PC 类似,依然存在一致性问题。

4. TCC


TCC 是柔性事务,而上面介绍的都是刚性事务。有时候,一个技术问题,可以通过业务建模来实现。

2PC 和 3PC 在概念上看起来虽然简单,但放在分布式环境中,考虑各种超时和宕机问题,如果考虑的周全,那可真是要了老命。

2PC 的框架还是比较多的,但 3PC 全网找了个遍,发现有名的实现几乎没有。

不要伤心,我们有更容易理解,更加直观的分布式事务。那就是 TCC,2007 年的老古董。

TCC 就是大名鼎鼎的补偿事务,是互联网环境最常用的分布式事务。它的核心思想是:为每一个操作,都准备一个确认动作和相应的补偿动作,一共 3 个方法。

与其靠数据库,不如靠自己的代码!2PC,3PC,都和数据库绑的死死的,TCC 才是码农的最爱(意思就是说,你要多写代码)。

如图,TCC 同样分为三个阶段,但非常的粗暴!

  • try 尝试阶段 尝试锁定资源

  • confirm 确认阶段 尝试将锁定的资源进行提交

  • cancel 取消阶段 其中某个环节执行失败,将发起事务取消动作

看起来这三个阶段,是 2 阶段提交的一种?完全不是。但它们的过程可以比较一下。

TCC 2PCTry 业务逻辑Confirm commit-request/voting + commitCancel rollback复制代码

复制代码

从上面可以看出来,2PC 是一种对事务过程的划分,而 TCC 是对正常情况的提交和异常情况的补偿。相对于传统的代码,try 和 confirm 两者加起来,才是真正的业务逻辑。

TCC 是非常容易理解的,但它有一个大的前提,就是这三个动作必须都是幂等的,对业务有一定的要求。拿资金转账来说,try 就是冻结金额;confirm 就是完成扣减;cancel 就是解冻,只要对应的订单号是一直的,多次执行也不会有任何问题。

由于 TCC 事务的发起方,直接在业务节点即可完成,和 TCC 的代码在同一个地方。所以,TCC 并不需要一个额外的协调者和事务处理器,它存放在本地表或者资源中即可。

是的,它也要记录一些信息,哪怕是 HashMap 里,否则它根据啥回滚呢?

4.1 问题

TCC 事务,需要较多的编码,以及正确的 try 和 confirm 划分。由于没有中心协调器,不需要阻塞,TCC 的并发量较高,被互联网业务广泛应用。

团队要有能力设计 TCC 接口,将其拆分成正确的 Try 和 Confirm 阶段,实现业务逻辑的分级。

4.2 框架

ByteTCC、tcc-transaction、seata 等。

5. SAGA


SAGA 也是一个柔性事务。

saga 的历史更久远,要追溯到 1987 年的一篇论文,可以说是瓶旧酒。它主要处理的是长活事务,但它不保证 ACID,只保证最终一致性。

所谓长活事务,可以被分解成交错运行的子事务,它通过消息,来协调一系列的本地子事务,来达到最终的一致性。

我们可以把 SAGA 编排器,想象成一个状态机。每当处理完一条消息,它就能够直到要执行的下一条消息(子事务)。

比如,我们把事务 T,拆分成了 T1,T2,T3,T4。那么我们就必须为这些子事务,提供相应的执行逻辑补偿逻辑。没错,和 TCC 一样,不过比 TCC 少了一步Try动作,同样要求这些操作是幂等的。

你瞧瞧,其实 SAGA 的概念很好理解,你就按照正常的业务逻辑去执行就行了。只不过如果在任何一步发生了异常,就要把前面所提交的数据全部回滚(补偿)。唯一特殊的是,它通常是通过消息驱动来完成事务运转的。

如果你非要追求它的本质,那就是 SAGA 和 TCC 一样,都是先记录执行轨迹,然后通过不断地重试达到最终状态。

上图是rob vettor所绘制的一个典型的 SAGA 事务拆分图。在图中,黑色的线为正常业务流程,红色的线为补偿业务流程。这是一个简单的电子商务结账流程,整个交易跨了 5 个微服务,可以说是非常大的长事务了。

可以看到,这样的事务流转,靠文字描述已经是不好理解了,所以 SAGA 通常会配备一个流程编辑器,直接来把事务编排的过程可视化。

5.1 问题

那问题就有意思多了。

  1. 嵌套问题。SAGA 只允许两层嵌套,因为靠消息流转本来就非常复杂了,嵌套层次深在性能和时序上都不允许

  2. 如果你的事务包含很多子事务,那么很有可能在某个阶段就执行失败了。但如果补偿操作也发生问题了呢?极端情况下,需要人工参与。在很多时候,需要记录日志(saga log)来配合完成

  3. 由于这些小事务并不是同时提交的,所以在执行的过程中,会产生脏数据,这和数据库的 read uncommited 的概念是一样的

5.2 框架

在《微服务架构设计模式》的第四章中,说明了 SAGA 的具体使用示例,现在网络上的大多数文章都来自于此。但据我所知,使用 SAGA 的互联网公司并不是很多,倒是使用 TCC 的比较多一些(可能是遇到的分布式事务都不是长事务)。

seata 同样提供了 SAGA 的方式,主要使用的是状态机驱动的编排模式。为了支持事务的编排,seata 提供了一个专用的流程编辑器(在线)。

http://seata.io/saga_designer/index.html``复制代码

复制代码

设计完毕之后,就可以导出为 JSON 文件,解析之后可以写入到数据库中。

bytetcc 虽然叫 tcc,它也支持 SAGA。

5.3 SAGA vs TCC

上面也提到,我在平常工作中,用到 TCC 比 SAGA 更多一些,也是由于业务场景确定的。下面简单的对比一下。

  1. 开发难度。TCC 的开发难度是比 SAGA 要高的,因为它需要处理 Try 阶段来冻结资源,而 SAGA 是直接执行本地事务

  2. 脏读问题。TCC 不存在脏读,因为 try 阶段并不影响数据;SAGA 会在小事务之间,或者 cancel 之间出现脏读

  3. 效率问题。TCC 无论成功失败,都需要和参与方交互两次;SAGA 在正常情况下交互一次,异常情况下交互两次,所以效率要高

那么如何才能正确的掌握Redis呢?

为了让大家能够在Redis上能够加深,所以这次给大家准备了一些Redis的学习资料,还有一些大厂的面试题,包括以下这些面试题

  • 并发编程面试题汇总

  • JVM面试题汇总

  • Netty常被问到的那些面试题汇总

  • Tomcat面试题整理汇总

  • Mysql面试题汇总

  • Spring源码深度解析

  • Mybatis常见面试题汇总

  • Nginx那些面试题汇总

  • Zookeeper面试题汇总

  • RabbitMQ常见面试题汇总

JVM常频面试:

Redis高频面试笔记:基础+缓存雪崩+哨兵+集群+Reids场景设计

Mysql面试题汇总(一)

Redis高频面试笔记:基础+缓存雪崩+哨兵+集群+Reids场景设计

Mysql面试题汇总(二)

Redis高频面试笔记:基础+缓存雪崩+哨兵+集群+Reids场景设计

Redis常见面试题汇总(300+题)

Redis高频面试笔记:基础+缓存雪崩+哨兵+集群+Reids场景设计

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

…(img-yod48hWV-1715062754207)]

Mysql面试题汇总(一)

[外链图片转存中…(img-MCyQ9ISn-1715062754207)]

Mysql面试题汇总(二)

[外链图片转存中…(img-vPO4lI7r-1715062754207)]

Redis常见面试题汇总(300+题)

[外链图片转存中…(img-KEaUVGkh-1715062754208)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

  • 9
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值