其他分享
首页 > 其他分享> > Seata分布式事务理论

Seata分布式事务理论

作者:互联网

文章目录

前面两篇文章主要介绍了Seata环境搭建和Seata基本使用,这篇来学习下分布式事务原理

1. 什么是分布式事务

分布式架构对应的是单体架构。随着业务复杂度和用户体验要求提高,单体架构已经无法满足互联网产品架构的需求,逐渐演变出了分布式架构

分布式架构下,需要服务与服务之间的远程协作才能完成一个用户操作,这种分布式系统环境下由不同的服务之间通过网络远程协作完成事务称之为分布式事务,例如创建订单减库存事务,银行转账事务等都是分布式事务

分布式架构中,每个服务负责不同的业务,各服务之间互相调用:

在这里插入图片描述

2. CAP 理论

2.1 CAP理论

CAP原则又叫 CAP 定理,指的是在一个分布式系统中,不可能同时满足以下三点:一致性(C)、可用性(A)、分区容错性(P)

在这里插入图片描述

简单的说:要求每个人看到的数据必须一致。

指强一致性,在写操作完成后开始的任何读操作都必须返回该值,也就是说,在一致性系统中,一旦客户端将值写入任何一台服务器并获得响应,那么之后客户端从其他任何服务器读取的都是刚写入的数据。

一致性保证了不管向哪台服务器写入数据,其他的服务器能实时同步数据

简单的说:要求系统任何时候都可用,哪怕每个用户看到的数据不一样

可用性是指:每次向未崩溃的节点发送请求,总能保证收到响应数据(允许不是最新数据)

部分服务器因网络问题,业务依然能够继续运行

一个分布式系统里面,节点组成的网络本来应该是连通的,然而可能因为一些故障,使有些节点之间不连通了,整个网络就分成了几块区域,数据就散布在了这些不连通的区域中,这就叫分区。

分布式系统在遇到任何网络分区故障的时候,仍然能够对外提供满足一致性和可用性的服务。

2.2 A 和 C 之间取舍

CAP理论告诉我们,一个分布式系统不可能同时满足这三个需求,最多只能同时满足其中的两项。

在分布式系统中,如果选择了 CA,舍弃了 P,说白了就是一个单体架构,这是不允许的,所以必须满足 CAP中的 P,此时只能在 C/A 之间作出取舍。

举个例子,来说明CAP理论的场景:

淘宝是分布式架构,首先肯定要满足分区容错性(P),在购物时,淘宝肯定要保证系统的可用性(A),因为它不可能要求对于商品的点赞数要求数据强一致性(C),数据的强一致性要求每个用户看到的数据必须一致。如果要求数据的强一致性,那系统应该早崩了。

2.3 一致性分类

在分布式架构中,CAP理论只能在 CA 之间选择,在分布式事务的最终解决方案中一般选择牺牲一致性来获取可用性和分区容错性

这里的 “牺牲一致性” 并不是完全放弃数据的一致性,而是放弃强一致性而换取弱一致性,也就是说在一段时间后,数据的一致性会得到保证,数据可以在系统没有压力的时候慢慢恢复。

一致性可以分为以下三种:

系统中的某个数据被成功更新后,后续任何对该数据的读取操作都将得到更新后的值,简言之,在任意时刻,所有节点中的数据是一样的。

一个集群需要对外部提供强一致性,所以只要集群内部某一台服务器的数据发生了改变,那么就需要等待集群内其他服务器的数据同步完成后,才能正常的对外提供服务

保证了强一致性,务必会损耗可用性

系统中的某个数据被更新后,后续对该数据的读取操作可能得到更新后的值,也可能是更改前的值,但即使过了不一致时间窗口这段时间后,后续对该数据的读取也不一定是最新值。

所以说,可以理解为数据更新后,如果能容忍后续的访问只能访问到部分或者全部访问不到,则是弱一致性。

例如 12306 买火车票,虽然最后看到还剩下几张余票,但是只要选择购买就会提示没票了,这就是弱一致性。

不保证在任意时刻任意节点上的同一份数据都是相同的,但是随着时间的迁移,不同节点上的同一份数据在一段时间后,节点间的数据会最终达到一致状态。

4. 分布式事务解决方案

在分布式架构下,每个服务节点只知晓自己操作的失败或者成功,无法得知其他节点的状态。

当一个事务跨多个服务节点时,为了保持事务的原子性与一致性,而引入一个协调者来统一掌控所有参与者的操作结果,并指示它们是否要把操作结果进行真正的提交或者回滚

4.1 二阶段提交(2PC)

二阶段提交协议(Two-phase Commit,即 2PC)是常用的分布式事务解决方案,即将事务的提交过程分为两个阶段来进行处理。两个阶段分别为:准备阶段、提交阶段

参与的角色:

4.1.1 准备阶段

这是两阶段的第一段,这一阶段只是准备阶段,由事务的协调者发起询问参与者是否可以提交事务,但是这一阶段并未提交事务,流程图如下图:

在这里插入图片描述

4.1.2 提交阶段

提交执行阶段属于 2PC 的第二阶段,协调者发起正式提交事务的请求,当所有参与者都回复同意时,则意味着完成事务,流程图如下:

在这里插入图片描述

但是,如果任意一个参与者节点在第一阶段返回的消息为终止,或者协调者节点在第一阶段的询问超时之前无法获取所有参与者节点的响应消息时,那么这个事务将会被回滚。

回滚的流程图如下:

在这里插入图片描述

二阶段提交的事务正常提交的完整流程如下图:

在这里插入图片描述

二阶段提交事务回滚的完整流程如下图:

在这里插入图片描述

4.1.3 二阶段提交优缺点

2PC看起来确实能够提供原子性的操作,但二阶段提交还是有几个缺点:

2PC 的优点:尽量保证了数据的强一致,适合对数据强一致要求很高的关键项目

4.2 三阶段提交(3PC)

三阶段提交,是二阶段提交的改进版本,三阶段提交有两个改动点

也就是说,除了引入超时机制之外,3PC2PC的准备阶段再次一分为二。这样三阶段提交就有 CanCommitPreCommitDoCommit三个阶段,处理流程如下:

在这里插入图片描述

4.2.1 CanCommit 阶段

3PCCanCommit阶段其实和 2PC的准备阶段很像,协调者向参与者发送 commit请求,参与者如果可以提交就返回 Yes响应,否则返回 No响应

CanCommit阶段流程如下图:

在这里插入图片描述

4.2.2 PreCommit 阶段

协调者根据参与者的反应情况来决定是否可以进行事务的 PreCommit操作,根据响应情况,有以下两种可能。

假如所有参与者均反馈 yes,协调者预执行事务

在这里插入图片描述

假如有任何一个参与者向协调者发送了 No响应,或者等待超时之后,协调者都没有接到参与者的响应,那么就执行事务的中断。

在这里插入图片描述

4.2.3 doCommit 阶段

该阶段进行真正的事务提交,也可以分为以下两种情况

进入阶段 3 后,无论协调者出现问题,或者协调者与参与者网络出现问题,都会导致参与者无法接收到协调者发出的 doCommit 请求或 abort 请求。此时,参与者都会在等待超时之后,继续执行事务提交。

执行提交

在这里插入图片描述

中断事务:任何一个参与者反馈 no,或者等待超时后协调者尚无法收到所有参与者的反馈,即中断事务:

在这里插入图片描述

4.2.4 三阶段提交优缺点

优点:相比二阶段提交,三阶段提交降低了阻塞范围,在等待超时后协调者或参与者会中断事务。避免了协调者单点问题,阶段 3 中协调者出现问题时,参与者会继续提交事务

缺点:数据不一致问题依然存在,当在参与者收到 preCommit请求后等待 doCommit指令时,此时如果协调者请求中断事务,而协调者无法与参与者正常通信,会导致参与者继续提交事务,造成数据不一致

4.3 TCC (事务补偿)

TCCTry Confirm Cancel)方案是一种应用层面侵入业务的两阶段提交。是目前最火的一种柔性事务方案,其核心思想是:针对每个操作,都要注册一个与其对应的确认和补偿(撤销)操作

TCC分为两个阶段,分别如下:

第一阶段:Try,主要是对业务系统做检测及资源预留 (加锁,锁住资源)

第二阶段:本阶段根据第一阶段的结果,决定是执行 confirm还是 cancel

在这里插入图片描述

为了方便理解,下面以电商下单为例进行方案解析,这里把整个过程简单分为扣减库存,订单创建 2 个步骤,库存服务和订单服务分别在不同的服务器节点上。

假设商品库存为 100,购买数量为2,这里检查和更新库存的同时,冻结用户购买数量的库存,同时创建订单,订单状态为待确认。

4.3.1 Try 阶段

TCC机制中的 Try仅是一个初步操作,它和后续的确认一起才能真正构成一个完整的业务逻辑,这个阶段主要完成:

在这里插入图片描述

4.3.2 Confirm / Cancel 阶段

根据 Try阶段服务是否全部正常执行,继续执行确认操作(Confirm)或取消操作(Cancel

ConfirmCancel操作满足幂等性,如果 ConfirmCancel操作执行失败,将会不断重试直到执行完成

Confirm:当 Try阶段服务全部正常执行, 执行确认业务逻辑操作,业务如下图:

在这里插入图片描述

这里使用的资源一定是 Try阶段预留的业务资源。在 TCC事务机制中认为,如果在 Try阶段能正常的预留资源,那 Confirm一定能完整正确的提交

Confirm阶段也可以看成是对 Try阶段的一个补充,Try+Confirm 一起组成了一个完整的业务逻辑

Cancel:当 Try阶段存在服务执行失败, 进入 Cancel阶段,业务如下图:

在这里插入图片描述

Cancel取消执行,释放 Try阶段预留的业务资源,上面的例子中,Cancel操作会把冻结的库存释放,并更新订单状态为取消。

4.3.3 最终一致性保证

4.3.4 方案总结

TCC事务机制相对于传统事务机制(X/Open XA),TCC事务机制相比于上面介绍的 XA事务机制,有以下优点:

缺点:TCCTryConfirmCancel操作功能要按具体业务来实现,业务耦合度较高,提高了开发成本

4.4 本地消息表

本地消息表核心思路是:将分布式事务拆分成本地事务进行处理

角色:事务主动方、事务被动方

通过在事务主动发起方额外新建事务消息表,事务发起方处理业务和记录事务消息在本地事务中完成,轮询事务消息表的数据发送事务消息,事务被动方基于消息中间件消费事务消息表中的事务

这样可以避免以下两种情况导致的数据不一致性:

整体的流程如下图:

在这里插入图片描述

上图中整体的处理步骤如下:

一些必要的容错处理如下:

优点

缺点

4.5 MQ 事务方案(可靠消息事务)

基于 MQ的分布式事务方案其实是对本地消息表的封装,将本地消息表放在 MQ内部,其他方面的协议基本与本地消息表一致。

MQ事务方案整体流程和本地消息表的流程很相似,如下图:

在这里插入图片描述

从上图可以看出和本地消息表方案唯一不同就是将本地消息表存在了 MQ内部,而不是业务数据库中

那么 MQ内部的处理尤为重要,下面主要基于 RocketMQ4.3之后的版本介绍 MQ的分布式事务方案

在本地消息表方案中,保证事务主动方发写业务表数据和写消息表数据的一致性是基于数据库事务,RocketMQ的事务消息相对于普通 MQ提供了 2PC的提交接口,方案如下:

正常情况:事务主动方发消息

在这里插入图片描述

这种情况下,事务主动方服务正常,没有发生故障,发消息流程如下:

异常情况:事务主动方消息恢复

在这里插入图片描述

在断网或者应用重启等异常情况下,图中 4提交的二次确认超时未到达 MQ Server,此时处理逻辑如下:

优点:

相比本地消息表方案,MQ事务方案优点是:

缺点

4.6 最大努力通知

最大努力通知也称为定期校对,是对 MQ事务方案的进一步优化。它在事务主动方增加了消息校对的接口,如果事务被动方没有接收到消息,此时可以调用事务主动方提供的消息校对的接口主动获取

最大努力通知的整体流程如下图:

在这里插入图片描述

在可靠消息事务中,事务主动方需要将消息发送出去,并且消息接收方成功接收,这种可靠性发送是由事务主动方保证的

但是最大努力通知,事务主动方尽最大努力(重试,轮询…)将事务发送给事务接收方,但是仍然存在消息接收不到,此时需要事务被动方主动调用事务主动方的消息校对接口查询业务消息并消费,这种通知的可靠性是由事务被动方保证的

最大努力通知适用于业务通知类型,例如微信交易的结果,就是通过最大努力通知方式通知各个商户,既有回调通知,也有交易查询接口

4.7 Saga 事务

Saga事务核心思想是:将长事务拆分为多个本地短事务,由 Saga事务协调器协调,如果正常结束那就正常完成,如果某个步骤失败,则根据相反顺序一次调用补偿操作

4.7.1 Saga基本协议

Saga事务基本协议如下:

TCC事务补偿机制有一个预留 (Try) 动作,相当于先报存一个草稿,然后才提交,事务没有预留动作,直接提交

对于事务异常,Saga提供了两种恢复策略,分别为:向后恢复、向前恢复

4.7.2 向后恢复 (backward recovery)

在执行事务失败时,补偿所有已完成的事务,是“一退到底”的方式,如下图:

在这里插入图片描述

从上图可知事务执行到了支付事务T3,但是失败了,因此事务回滚需要从C3,C2,C1依次进行回滚补偿

对应的执行顺序为:T1,T2,T3,C3,C2,C1

这种做法的效果是撤销掉之前所有成功的子事务,使得整个 Saga的执行结果撤销

4.7.3 向前恢复 (forward recovery)

对于执行不通过的事务,会尝试重试事务,这里有一个假设就是每个子事务最终都会成功,流程如下图:

在这里插入图片描述

适用于必须要成功的场景,事务失败了重试,不需要补偿

4.7.4 Saga事务实现方式

Saga事务有两种不同的实现方式,分别如下:命令协调(Order Orchestrator)、事件编排(Event Choreographyo

4.7.4.1 命令协调

中央协调器(Orchestrator,简称 OSO)以命令/回复的方式与每项服务进行通信,全权负责告诉每个参与者该做什么以及什么时候该做什么。整体流程如下图:

在这里插入图片描述

上图步骤如下:

中央协调器必须事先知道执行整个订单事务所需的流程(例如通过读取配置)。如果有任何失败,它还负责通过向每个参与者发送命令来撤销之前的操作来协调分布式的回滚

基于中央协调器协调一切时,回滚要容易得多,因为协调器默认是执行正向流程,回滚时只要执行反向流程即可

4.7.4.2 事件编排

没有中央协调器(没有单点风险)时,每个服务产生并观察其他服务的事件,并决定是否应采取行动

在事件编排方法中,第一个服务执行一个事务,然后发布一个事件。该事件被一个或多个服务进行监听,这些服务再执行本地事务并发布(或不发布)新的事件

当最后一个服务执行本地事务并且不发布任何事件时,意味着分布式事务结束,或者它发布的事件没有被任何 Saga参与者听到都意味着事务结束

在这里插入图片描述

上图步骤如下:

4.7.5 Saga事务优缺点

4.7.5.1 优点

命令协调设计的优点如下:

事件编排设计优点如下:

4.7.5.2 缺点

命令协调设计缺点如下:

事件编排设计缺点如下:

由于 Saga 模型中没有 Prepare 阶段,因此事务间不能保证隔离性。

当多个 Saga事务操作同一资源时,就会产生更新丢失、脏数据读取等问题,这时需要在业务层控制并发,例如:在应用层面加锁,或者应用层面预先冻结资源

4.8 总结

总结一下各个方案的常见的使用场景:

5. Seata

上面介绍了这么多的分布式事务的理论知识,Seata就是理论知识的落地实现。

Seata是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata将为用户提供了 ATTCCSAGAXA事务模式,为用户打造一站式的分布式解决方案。

看完上面,再去看看Seata官方文档吧

https://seata.io/zh-cn/docs/overview/what-is-seata.html

标签:阶段,事务,Seata,协调者,消息,提交,参与者,分布式
来源: https://blog.csdn.net/zxd1435513775/article/details/122178290