再学分布式事务
Posted Shi Peng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了再学分布式事务相关的知识,希望对你有一定的参考价值。
一、背景知识
1.1、事务
事务需要具备ACID:以A给B转账为例
- A(Atomicity,原子性):A的钱减100,B的钱多100,要么全部成功,要么全部失败
- C(Consistency,一致性):A减100后,B一定多了100,这个数是一致的
- I(Isolation, 隔离性):多个事务互相不可见(读已提交、读未提交、可重复读、可串行化)
- D(Durability,持久性):转账后的数据会落盘持久存储,不会丢失。
1.2、分布式事务CAP理论
ACID的事务理论,在单个数据库情况下没问题。但在数据库分片时,不同数据库在不同的服务器上,这时ACID就失效了。这时要引入新的CAP理论。
- C(Consistency,一致性):A减100后,B一定多了100,这个数是一致的
- A(Availability,可用性):每个请求都会获得预期的响应
- P(Partition tolerance,分区容错性):即使服务器单个节点故障,转账请求依然可完成
在CAP理论中,CAP最多能同时满足两个,通常对于分布式系统,P是一定要保证的。所以通常在C、A之间做取舍。
二、分布式事务解决方案
分布式事务的场景解决方案有:
- 2PC
- 3PC
- TCC
- 本地消息表
- 消息事务-RocketMQ
- 最大努力通知
- Sagas
- 阿里分布式事务解决方案Fescar
2.1、2PC(两阶段提交)
2.1.1、特点
1、确保了强一致性C,但牺牲了可用性A。
2、不适合高并发场景。
2.1.2、两阶段提交的过程
举例:
订单服务A,需要调用 支付服务B 去支付,支付成功则处理购物订单为待发货状态,否则就需要将购物订单处理为失败状态。
第一阶段:投票阶段
第一阶段分三步:
1)协调者向参与者做事务询问
协调者向所有参与者发送事务预处理请求,称为prepare。
2)参与者执行本地事务,但不提交
所有参与者执行本地事务操作,但不会真正提交事务,然后向协调者回复说,我这可以处理 或 不可处理
3)参与者向协调者回复事务询问的结果
参与者如果成功执行了事务,回复Yes; 否则回复No
最终,第一阶段有两个结果:
1)所有参与者全部回复Yes
2)参与者有一个或多个回复No
第二阶段:提交/执行阶段(参与者都返回Yes)
第二阶段分两步:
1)协调者向参与者发送提交请求
如所有参与者都给协调者回复Yes, 则协调者向所有参与者节点发送Commit请求
2)参与者执行事务提交
参与者受到协调者的commit请求后,会执行本地事务commit操作,并在完成提交后释放整个事务执行期间占用的事务资源。
第二阶段:提交/执行阶段(异常流程)
异常条件:任何一个参与者回复No, 或等待超时后,协调者未收到所有参与者的反馈响应。
异常流程二阶段也分为两步:
1)发送回滚请求
协调者向所有参与者发送Rollback请求
2)事务回滚
参与者收到请求后,会回滚本地事务
2.1.3、2PC缺点
1、性能不好
无论第一阶段,还是第二阶段,所有参与者和协调者的资源都是被锁定的,只有当二阶段所有参与者的事务提交或回滚后,资源才会释放。所以性能不好
2、单节点故障
一旦协调者发送故障,参与者就会一直阻塞下去,无法继续完成事务操作。
2.2、3PC(三阶段提交)
3PC是为了解决2PC的阻塞问题:参与者在协调者恢复之前保持阻塞。所以3PC是2PC的改进版本。
三阶段的两个改动点:
1、引入超时机制:在协调者和参与者中都有超时机制。
2、在第一阶段和第二阶段中插入了一个准备节点,保证了在最后提交阶段之前,各参与节点的状态一致。
阶段1:CanCommit阶段
2PC的一阶段是本地事务执行后不commit, 等其他服务返回Yes, 由协调者发出commit请求后再真正执行commit。而3PC是指尝试获取数据库锁,如果可以,就返回Yes。
一阶段canCommit分两步:
1、事务询问
协调者向参与者发送canCommit请求,并等待参与者响应
2、响应反馈
参与者收到canCommit请求后,看自身是否可正常执行事务,回复Yes或No
阶段二:PreCommit阶段
如果一阶段参与者都返回Yes, 则进入PreCommit阶段,与2PC不同的是,除了参与者有超时,协调者也有超时机制
阶段三:DoCommit
这个跟2PC相同。
2.3、TCC(Try-Confirm-Cancel)补偿事务
TCC的try, confirm, cancel都有业务编码实现。
所以说2PC和3PC,都是基于数据库层做的,而TCC是基于业务层做的。
Try:指资源的预留和锁定
Confirm:确认操作,其实是真正的执行了
Cancel:撤销操作,指把预留阶段的动作撤销了。
TCC的思想跟2PC类似,先试探是否可执行(Try),然后真正的执行(Confirm),如果不行就回滚(Cancel)
比如一个事务要执行A、B、C三个操作,那么先对三个操作执行预留动作。如果都预留成功了那么就执行确认操作,如果有一个预留失败那就都执行撤销动作。
TCC 其实就是采用的补偿机制,其核心思想是:针对每个操作,都要注册一个与其对应的确认和补偿(撤销)操作。
TCC分为三个阶段:
1)Try 阶段主要是对业务系统做检测及资源预留
2)Confirm 阶段主要是对业务系统做确认提交,Try阶段执行成功并开始执行 Confirm阶段时,默认 Confirm阶段是不会出错的。即:只要Try成功,Confirm一定成功。
3)Cancel 阶段主要是在业务执行错误,需要回滚的状态下执行的业务取消,预留资源释放。
举个例子,假入 Bob 要向 Smith 转账,思路大概是:
我们有一个本地方法,里面依次调用
1、首先在 Try 阶段,要先调用远程接口把 Smith 和 Bob 的钱给冻结起来。
2、在 Confirm 阶段,执行远程调用的转账的操作,转账成功进行解冻。
3、如果第2步执行成功,那么转账成功,如果第二步执行失败,则调用远程冻结接口对应的解冻方法 (Cancel)。
跟2PC相比,实现更简单,但数据一致性更差
缺点:由于步骤2和步骤3都有可能失败,要通过业务来实现补偿机制。
TCC 对业务的侵入较大和业务紧耦合,需要根据特定的场景和业务逻辑来设计相应的操作。
还有一点要注意,撤销和确认操作的执行可能需要重试,因此还需要保证操作的幂等。
相对于 2PC、3PC ,TCC 适用的范围更大,但是开发量也更大,毕竟都在业务上实现,而且有时候你会发现这三个方法还真不好写。不过也因为是在业务上实现的,所以TCC可以跨数据库、跨不同的业务系统来实现事务。
2.4、本地消息表
本地消息表,是ebay提出的,是BASE理论的应用,是最终一致性。
本地消息表,是业界使用最多的。
本地消息表的核心思想是将分布式事务拆分成多个本地事务进行处理。
1、消息生产方:
需要额外建一个消息数据库表,并记录消息发送状态。消息表和业务数据要在一个事务里提交,也就是说他们要在一个数据库里面。然后消息会经过MQ发送到消息的消费方。如果消息发送失败,会进行重试发送。
例如:A给B转账100元,A减100元的操作记录到本地的数据库表里,然后该动作经由MQ让B来消费
2、消息消费方:
需要消费这个消息,并完成自己的业务逻辑。此时如果本地事务处理成功,表明已经处理成功了,如果处理失败,那么就会重试执行。如果是业务上面的失败,可以给生产方发送一个业务补偿消息,通知生产方进行回滚等操作。
例如:B消费A减100的消息,然后自己加100元,如失败,把失败的结果通知A,A回滚。
在上面的例子中,A和B的数据无法同时提交,所以无法保证事务的强一致性,只能保证最终一致性。
处理不成功,可重试,但重试要保证消息的幂等性。
优点: 一种非常经典的实现,避免了分布式事务,实现了最终一致性。
缺点: 消息表会耦合到业务系统中,如果没有封装好的解决方案,会有很多杂活需要处理。
2.5、MQ事务消息
RocketMQ支持事务消息,具体实现方式:
Step1、先给 Broker 发送事务消息即半消息
半消息不是说一半消息,而是这个消息对消费者来说不可见,然后发送成功后发送方再执行本地事务。
例如,A向B转账100元,先发送转账请求到RocketMQ,这条消息对消费者不可见,然后A执行减100元操作。
Step2、再根据本地事务的结果向 Broker 发送 Commit 或者 RollBack 命令。
例如:A减100元操作成功了,A向MQ发送成功或失败结果,成功则把上面的“一半消息”变成可消费消息,失败则回滚掉这条“一半消息”。
MQ的事务消息实现了事务的最终一致性。
2.6、Sagas 事务
其核心思想就是拆分分布式系统中的长事务为多个短事务,或者叫多个本地事务,然后由 Sagas 工作流引擎负责协调,如果整个流程正常结束,那么就算是业务成功完成,如果在这过程中实现失败,那么Sagas工作流引擎就会以相反的顺序调用补偿操作,重新进行业务回滚。
比如我们一次关于购买旅游套餐业务操作涉及到三个操作,他们分别是预定车辆,预定宾馆,预定机票,他们分别属于三个不同的远程接口。可能从我们程序的角度来说他们不属于一个事务,但是从业务角度来说是属于同一个事务的。
他们的执行顺序如上图所示,所以当发生失败时,会依次进行取消的补偿操作。
因为长事务被拆分了很多个业务流,所以 Sagas 事务模型最重要的一个部件就是工作流或者你也可以叫流程管理器(Process Manager),工作流引擎和Process Manager虽然不是同一个东西,但是在这里,他们的职责是相同的。
以上是关于再学分布式事务的主要内容,如果未能解决你的问题,请参考以下文章
分布式事务——分布式事务简介分布式事务框架 Seata(AT模式Tcc模式Tcc Vs AT)分布式事务—MQ