SpringCloud--分布式事务实现

一、分布式事务

首先要明白事务是指数据库中的一组操作,这些操作要么全部成功执行,要么全部不执行,以保持数据的一致性和完整性。在本地事务中,也就是传统的单机事务,必须要满足原子性(Atomicity)一致性(Consistency)隔离性(Isolation)持久性(Durability)四个特性,通常称为ACID特性。而分布式事务是指跨越多个分布式系统的事务,不再是单机事务,其中涉及到多个独立服务。分布式事务主要是为了保证这多个跨服务的系统之间的操作的一致性和原子性。

二、分布式系统面临的问题

在分布式系统中,通常是根据业务逻辑分成多个微服务独立部署,且每个微服务都有自己单独的数据源。以最常见的用户购买商品的业务逻辑,可以分为3个微服务:

  • 订单服务(Order):用户根据商品的库存量来创建订单。
  • 仓储服务(Stock):创建订单成功后对给定的商品扣除库存量。
  • 账户服务(Account):订单支付成功后从用户账户中扣除余额。

当用户购买一件商品从下单到支付成功,总共要涉及3个服务的操作。由于各个服务间调用可能存在网络延迟、节点故障、通信失败等原因,导致分布式事务无法像单个系统的事务那样简单的就能实现ACID特性。这期间往往会产生许多问题,最常见的如下:

  1. 部分失败:在一个分布式事务中,有些参与者执行成功,而其他参与者执行失败,导致事务的部分操作成功,部分操作失败。
  2. 数据不一致:在一个分布式事务中,数据的一致性无法保证,可能因为参与者之间的数据冲突或者数据同步延迟。

三、分布式理论基础

3.1 CAP定理

CAP定理是分布式当中一个非常重要的理论,指的是在一个分布式系统中一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance):

  • 一致性(Consistency):在任何时刻,对于同一个数据项,所有节点上的值都是相同的。
  • 可用性(Availability):系统在任何时候都能够响应客户端请求,不会出现宕机或不可用的情况。
  • 分区容错性(Partition tolerance):分布式系统中的节点之间可能会出现网络故障,但是无论哪个节点出现故障,整个分布式系统任然能够对外提供服务。

CAP定理中不可能同时满足这三者,最多只能同时满足其中两项:

  • 放弃P(CA):在分布式系统中,系统间的网络不可能100%保证正常,一定会有故障的时候,又想在节点故障的情况下还保证节点间数据的一致性和可用性是不现实的。因此分区容错性不可避免。
  • 放弃A(CP):就是在节点存在故障后,为了保证各个节点间数据的强一致性,就必须等故障节点恢复正常后,再将数据同步过去,在等待故障节点恢复正常的这段时间服务处于阻塞状态,不可用。也就是放弃服务的可用性,从而保证节点间数据的强一致性。
  • 放弃C(AP):就是在节点存在故障后,不用再等故障节点恢复正常,依旧对外提供服务,只不过使用的是故障前的数据提供服务。也就是可能存在节点间的数据不一致,用放弃数据强一致性来实现服务的可用性。其实这里放弃一致性,并不是完全不需要数据一致性,是指放弃数据的强一致性,保留数据的最终一致性。

CAP理论具体应用:

  • Redis :属于 cp 模型。
  • Redis-cluster 属于 ap 模型
  • Zookeeper:属于cp模型。
  • MongoDB :属于cp模型。
  • Eureka:属于ap模型。
3.2 BASE理论

CAPBASE理论指的是:基本可用(Basically Available),软状态(Soft State),最终一致性(Eventual Consistency),核心思想是即便无法做到强一致性,但应该采用适合的方式保证最终一致性。

  • BA:Basically Available 基本可用,分布式系统在出现故障的时候,允许损失部分可用性,即保证核心可用。
  • S:Soft State 软状态,允许系统存在中间状态,而该中间状态不会影响系统整体可用性。
  • E:Eventual Consistency 最终一致性,系统中的所有数据副本经过一定时间后,最终能够达到一致的状态。

一致性可分为以下3类:

  • 强一致性:在任意时刻,所有节点看到的数据都必须是一样的。
  • 弱一致性:数据的更新可能会出现延迟,允许在延迟的这段时间内,节点看到的数据不是最新的。
  • 最终一致性:不保证在任意时刻任意节点上的同一份数据都是相同的,但是在一段时间后,节点间的数据会最终达到一致状态。

四、Seata框架

Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。
在这里插入图片描述

4.1 Seata中三个重要的角色
  1. TC (Transaction Coordinator) 事务协调者:维护全局和分支事务的状态,驱动全局事务提交或回滚。
  2. TM (Transaction Manager) 事务管理器:定义全局事务的范围、向TC申请开始全局事务、向TC申请提交或回滚全局事务。
  3. RM (Resource Manager) - 资源管理器:管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
4.2 Seata事务整体执行流程
  1. 由TM向TC申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的XID;
  2. XID会在微服务调用链路的上下文中传播;
  3. RM向TC注册分支事务,纳入XID对应全局事务的范围;
  4. RM驱动分支事务的执行,并报告分支事务的执行结果给TC;
  5. TM向TC发起针对XID的全局事务提交或回滚决议;
  6. TC根据RM报告的实际分支事务的执行结果进行决策,TC会向RM发送一个提交或回滚消息。
  7. RM会将这个提交或回滚消息广播给所有参与该全局事务的分支服务,让它们各自提交或回滚分支事务。

五、Seata中四种事务模式

5.1 AT模式

AT模式是Seata的默认模式,在该模式下Seata工作在应用层,无业务侵入,主要是通过对本地关系数据库的分支事务的协调来完成全局事务。

5.1.1 前提
  • 基于支持本地 ACID 事务的关系型数据库。
  • Java 应用,通过 JDBC 访问数据库。
5.1.2 整体机制

两阶段提交协议的演变:

  • 一阶段:业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。
  • 二阶段:
    • 提交异步化,非常快速地完成。
    • 回滚通过一阶段的回滚日志进行反向补偿。
5.1.3 写隔离

Seata通过 全局锁 来保证多个全局事务之间的写隔离,从而防止脏写的发生。全局锁 本身就是一条记录,由xid-事务、table-表名、pk-数据的行组成,全局锁 由事务协调者TC控制,只有持有该全局锁的全局事务,才具备本地事务的执行权。

  • 一阶段本地事务提交前,需要确保先拿到 全局锁
  • 拿不到 全局锁 ,不能提交本地事务。
  • 全局锁 的尝试被限制在一定范围内,超出范围将放弃,并回滚本地事务,释放本地锁。
    在这里插入图片描述
    在这整个过程中全局事务2都没能拿到 全局锁,也就没能提交全局事务,所以不会发生 脏写 的问题。
5.1.4 读隔离

在数据库本地事务隔离级别 读已提交(Read Committed) 或以上的基础上,Seata(AT 模式)的默认全局隔离级别是 读未提交(Read Uncommitted)。如果应用在特定场景下,必需要求全局的 读已提交 ,目前 Seata 的方式是通过 SELECT FOR UPDATE 语句的代理。
在这里插入图片描述
SELECT FOR UPDATE 语句的执行会申请 全局锁 ,如果 全局锁 被其他事务持有,则释放本地锁(回滚 SELECT FOR UPDATE 语句的本地执行)并重试。这个过程中,查询是被 block 住的,直到 全局锁 拿到,即读取的相关数据是 已提交 的,才返回。出于总体性能上的考虑,Seata 目前的方案并没有对所有 SELECT 语句都进行代理,仅针对 FOR UPDATE 的 SELECT 语句。

5.1.5 AT模式的工作流程

以更新 person 业务表的数据为例:update person set age = 18 where name = 'Tom';

一阶段:

  1. 解析 SQL:得到 SQL 的类型(UPDATE),表(person),条件(where name = ‘Tom’)等相关的信息。
  2. 查询前镜像:根据解析得到的条件信息,生成查询语句,定位数据。select id, name, since from product where name = 'TXC';
  3. 执行业务 SQL:更新这条记录的 age 为 18。
  4. 查询后镜像:根据前镜像的结果,通过 主键 定位数据。select id, name, age from person where id = 1;
  5. 插入回滚日志:把前、后镜像数据以及业务 SQL 相关的信息组成一条回滚日志记录,插入到 UNDO_LOG 表中。
  6. 提交本地事务前,向 TC 注册分支:申请 person 表中,主键值等于 1 的记录的 全局锁 。
  7. 拿到全局锁后,提交本地事务。
  8. 将本地事务提交的结果上报给 TC。

二阶段–回滚:

  1. 收到 TC 的分支回滚请求,开启一个本地事务,执行如下操作。
  2. 通过 XID 和 Branch ID 查找到相应的 UNDO LOG 记录。
  3. 数据校验:拿 UNDO LOG 中的后镜与当前数据进行比较,如果有不同,说明数据被当前全局事务之外的动作做了修改。这种情况,需要根据配置策略来做处理。
  4. 根据 UNDO LOG 中的前镜像和业务 SQL 的相关信息生成并执行回滚的语句。
  5. 提交本地事务,并把本地事务的执行结果(即分支事务回滚的结果)上报给 TC。

二阶段–提交:

  1. 收到 TC 的分支提交请求,把请求放入一个异步任务的队列中,马上返回提交成功的结果给 TC。
  2. 异步任务阶段的分支提交请求将异步和批量地删除相应 UNDO LOG 记录。
5.1.6 XA模式实现
  1. 添加配置seata:data-source-proxy-mode: AT
  2. 在需要分布式事务的业务代码上添加注解 @GlobalTransactional
5.1.7 AT模式的优缺点

优点:

  • 一阶段完成直接提交事务,释放数据库资源,性能比较好。
  • 没有代码侵入,框架自动完成回滚和提交。
  • 使用方便,在需要分布式事务的业务代码上添加注解@GlobalTransactional即可。

缺点:

  • 属于最终一致,对一致性的要求相对较低,中间可能会出现数据不一致的情况。
  • 由于AT模式依赖于本地事务,所以受限于本地事务管理器支持的隔离级别,可能无法满足某些特定的隔离需求。
5.2 TCC模式

TCC模式下,Seata也是在业务层面实现的二阶段提交方案,不过AT模式不同的是,TCC模式不再依赖本地事务,而是通过人工编码定义一个接口,接口中包含三个方法,供每个分支事务来实现各种的提交和回滚逻辑。因此,会有业务代码侵入。

// 定义一个全局事务的接口
public interface IGlobalService {
// 尝试预留或锁定资源
boolean tryTransfer();
// 最终的确认操作
boolean confirmTransfer();
// 最终的回滚操作
boolean cancelTransfer();
}
5.2.1 整体机制

也是基于两阶段提交:

  • 一阶段:尝试阶段,各个参与者尝试预留或锁定资源。
  • 二阶段:
    • 确认阶段,各个参与者进行最终的确认操作。
    • 取消阶段,各个参与者进行最终的确认操作。
5.2.2 TCC模式的工作流程

一阶段:
Try阶段(尝试阶段):在这个阶段,各个参与者尝试预留或锁定资源,并执行必要的前置检查。如果所有参与者的Try操作都成功,表示资源可用,并进入下一阶段。如果有任何一个参与者的Try操作失败,表示资源不可用或发生冲突,事务将中止。

二阶段:
Confirm阶段(确认阶段):在这个阶段,各个参与者进行最终的确认操作,将资源真正提交或应用到系统中。如果所有参与者的Confirm操作都成功,事务完成,提交操作得到确认。如果有任何一个参与者的Confirm操作失败,事务将进入Cancel阶段。

二阶段:
Cancel阶段(取消阶段):在这个阶段,各个参与者进行回滚或取消操作,将之前尝试预留或锁定的资源恢复到原始状态。如果所有参与者的Cancel操作都成功,事务被取消,资源释放。如果有任何一个参与者的Cancel操作失败,可能需要进行补偿或人工介入来恢复系统一致性。

5.2.3 用例实现
  1. 分支事务具体实现
public class BranchServiceImpl implements IGlobalService {@Overridepublic boolean tryTransfer() {// 尝试预留或锁定资源// 如果成功,返回 true;如果失败,返回 false}@Overridepublic boolean confirmTransfer() {// 最终的确认操作// 如果成功,返回 true;如果失败,返回 false}@Overridepublic boolean cancelTransfer() {// 进行回滚或取消操作// 如果成功,返回 true;如果失败,返回 false}
}
  1. 客户端调用
String xid = RootContext.getXID();
// 开启全局事务
TransactionContext context = new TransactionContext();
context.setXid(xid);
GlobalTransaction tx = GlobalTransactionContext.getCurrentOrCreate();
try {
// 调用参与者的tryTransfer方法
boolean tryResult = branchServiceImpl.tryTransfer();
if (tryResult) {
// 提交全局事务
tx.commit();
} else {
// 回滚全局事务
tx.rollback();
}
} catch (Exception e) {
// 异常时回滚全局事务tx.rollback();
}
5.2.4 TCC模式的优缺点

优点:

  • 一阶段直接提交事务,释放数据库资源,性能好;
  • 相比AT模型,无需生成快照,无需使用全局锁,性能最强;
  • 不依赖数据库事务,而是依赖补偿操作,可以用于非事务型数据库;

缺点:

  • 有代码侵入,需要人为的设计和编写try、Confirm和Cancel接口,太麻烦;
  • 软状态,事务是最终一致;
  • 需要考虑Confirm和Cancel的失败情况,做好幂等处理;
5.3 SAGA模式

Saga模式是将一个长事务分解为多个小的、可逆的事务片段,每个事务片段都是一个真实的本地事务。每个事务片段都有对应的补偿动作,补偿动作用于撤销因事务片段执行所造成的结果。
在这里插入图片描述

5.3.1 整体机制

Saga模式的提交过程也分为两个阶段:

  • 一阶段:直接提交子事务
  • 二阶段:成功则什么都不做;失败则执行补偿业务来回滚;
5.3.2 saga模式的工作流程

一阶段:执行正向操作

  1. 按照事务的逻辑顺序,依次执行正向操作。每个正向操作都会记录事务的执行状态。
  2. 如果所有的正向操作都成功执行,则事务提交完成。
  3. 如果某个正向操作失败,将会触发相应的补偿操作。

二阶段:执行补偿操作

  1. 按照逆序依次执行已经触发的补偿操作。补偿操作应该具备幂等性,以便可以多次执行而不会造成副作用。
  2. 如果所有的补偿操作都成功执行,则事务回滚完成。
  3. 如果补偿操作也失败,需要人工介入或其他手段来解决事务的一致性问题。
5.3.3 saga模式的优缺点

优点:

  • 事务参与者可以基于事件驱动实现异步调用,吞吐高;
  • 一阶段直接提交事务,无锁,性能好;
  • 补偿服务易于实现,不用编写TCC中的三个阶段,实现简单

缺点:

  • 软状态持续时间不确定,时效性差;
  • 没有锁,没有业务层面的事务隔离,会有脏写
5.4 XA模式

XA模式是事务资源(数据库、消息服务等)对 XA 协议的支持,以 XA 协议的机制来管理分支事务的一种事务模式。具有强一致性,牺牲了一定的可用性,无业务侵入。
在这里插入图片描述

5.4.1 整体机制

XA模式的提交过程也分为两个阶段:

  • 一阶段:准备阶段,各个分支事务执行完本地事务,但不提交本地事务。
  • 二阶段:
    • 提交阶段,各个分支事务同时进行提交本地事务操作。
    • 中断阶段,各个分支事务同时进行回滚本地事务操作。
5.4.2 XA模式的事务执行流程

一阶段:准备阶段

  1. 每个分支事务的RM注册分支事务到TC;
  2. 执行分支业务sql但不提交,继续持有数据库的锁;
  3. RM报告执行状态到TC;

二阶段:提交阶段

  1. TC检测各分支事务执行状态全部为成功;
  2. 通知所有RM提交本地事务;
  3. RM接收TC的通知,提交分支事务,并释放之前持有的数据库锁;

二阶段:中断阶段

  1. TC检测所有分支事务执行状态中有失败的;
  2. 通知所有RM回滚本地事务;
  3. RM接收TC的通知,回滚分支事务,并释放之前持有的数据库锁;
5.4.3 XA模式实现
  1. 添加配置seata:data-source-proxy-mode: XA
  2. 在需要分布式事务的业务代码上添加注解 @GlobalTransactional
5.4.4 XA模式的优缺点

优点:

  • 通过XA 协议的机制来管理分支事务实现简单,并且没有代码侵入;
  • 事务具有强一致性,确保所有参与者要么一起提交事务,要么一起中断事务;

缺点:

  • 必须依赖于支持XA 事务的数据库;
  • 由于一阶段不提交本地事务,所有的参与者都需要等待事务协调器的指令来进行提交或者回滚,期间可能造成阻塞,影响系统的吞吐量和并发性能。

六、四种模式对比

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/177768.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux安全之auditd审计工具使用说明

一、auditd工具简介 audited是Linux审核系统的用户空间组件。它负责将审核记录写入磁盘。查看日志是通过ausearch或aureport实用程序完成的。审核系统或加载规则的配置是使用auditctl实用程序完成的。在启动过程中,/etc/audit/audit.rules中的规则由auditctl读取并加…

【傻瓜级JS-DLL-WINCC-PLC交互】1.C#用windows窗体控件创建.net控件

思路 JS-DLL-WINCC-PLC之间进行交互,思路,先用Visual Studio创建一个C#的DLL控件,然后这个控件里面嵌入浏览器组件,实现JS与DLL通信,然后DLL放入到WINCC里面的图形编辑器中,实现DLL与WINCC的通信。然后PLC与…

visual c++ 2019 redistributable package

直接安装下面包只有24M Microsoft Visual C Redistributable 2019 x86: https://aka.ms/vs/16/release/VC_redist.x86.exe x64: https://aka.ms/vs/16/release/VC_redist.x64.exe ———————————————— 版权声明:本文为CSDN博主「kpacnB_Z」的原创文章…

uniapp设置手机通知权限

提醒用户开启通知权限,与unipush功能联用 效果图: 方法: 直接使用即可,在真机或模拟器运行 setPermissions() {// #ifdef APP-PLUS if (plus.os.name Android) { // 判断是Androidvar main plus.android.runtimeMainActivity…

oracle免费资源 终止实例 以及新建一台实例的折腾记录

事情的背景是这样的,我的一台oracle小鸡,不太好用的样子,有时候SSH连不上,有时候莫名其妙卡住。所以我就想把它重新安装一下系统,恢复成最初的样子。 然后在网上查资料,是有办法把系统重装一下的。但是略微…

抖去推--短视频账号矩阵系统saas工具源码技术开发

一、短视频矩阵系统搭建常见问题? 1、抖去推的短视频AI矩阵营销软件需要一定的技术水平吗? 答:不需要。产品简单易用,不需要具备专业的技术水平,即使是初学者,也能够轻松上手操作。 3、抖去推的短视频AI矩…

神经网络可视化——基于torchviz绘制模型的计算图

神经网络可视化——基于torchviz绘制模型的计算图 第一步、安装 graphviz 和 torchviz 库 第二步、编写代码生成计算图 第三步、安装graphviz软件 在深入理解深度学习模型时,可视化网络结构是一个非常有用的手段。今天介绍如何使用 torchviz 和 graphviz 来生成网…

很清楚展示GPT插件的调用过程,人工智能(AI)的潜在危险与好处 超级智能 未来

好处,未来 很清楚展示GPT插件的调用过程: 把请求和要求发chatGPT chatGPT返回markdown格式发给插件 插件返回结果给用户。 你不用别人用。 人工智能(AI)的最危险之处通常与以下几个方面有关: 自主决策能力过强&…

元宇宙3d服装数字化交互展示营销平台大幅提高客户满意度和口碑

web3D云展营销平台是以web3d开发、VR虚拟现实和计算机技术,以展品3D展示、数字人,AI,社交等技术打造,为 Web3D可视化提供了丰富的展示形式和效果,实现将线下展厅、展品在线上1:1复刻呈现的线上场景营销。 w…

企业软件手机app定制开发新趋势|网站小程序搭建

企业软件手机app定制开发新趋势|网站小程序搭建 随着移动互联网的快速发展和企业数字化转型的加速,企业软件手机App定制开发正成为一个新的趋势。这种趋势主要是由于企业对于手机App的需求增长以及现有的通用应用不能满足企业特定需求的情况下而产生的。 首先&#…

使用char.js 柱形方式显示 一年12个月的最高气温与最低气温

<!DOCTYPE html> <html> <head><title>气温图表</title><script src"https://cdn.jsdelivr.net/npm/chart.js"></script><style>#myChart{width:800px;height: 400px;}</style> </head> <body>&l…

【一文带你读懂docker,从入门到精通!】

dockerfile 是啥?dockerfile 用来构建 docker 镜像的文件。 前言 Docker 入门到精通 1、DockerFile 介绍 dockerfile 是啥?dockerfile 用来构建 docker 镜像的文件。 具体步骤&#xff1a; 1、编写一个 dockerfile 文件 2、docker build 构造一个镜像 3、docker run 运行…

Swift下如何使用#if条件编译

一、OC使用条件编译 OC中可以使用宏定义&#xff0c;再使用条件编译 #define USER_CUSTOM使用 #if USER_CUSTOM //其他代码 #endif二、Swift使用条件编译 Swift 不像ObjectC一样&#xff0c;通过定义一个变量&#xff0c;然后使用**#if #endif** 方法。swift需要设置一下才能…

计算机网络(超详解!) 第一节计算机网络的性能指标

1.速率 比特&#xff08;bit&#xff09;是计算机中数据量的单位&#xff0c;也是信息论中使用的信息量的单位。 比特&#xff08;bit&#xff09;来源于 binary digit&#xff0c;意思是一个“二进制数字”&#xff0c;因此一个比特就是二进制数字中的一个 1 或 0。 速率是…

aPEAR包绘制功能富集网络图

本期教程 前言 今天学习aPEAR包&#xff0c;绘制KEGG和GO功能富集网络图&#xff0c;用起来还是比较方便的&#xff0c;直接将clusterProfiler富集结果进行绘制&#xff0c;对人类、动物等分析结果非常方便。对于模式植物&#xff0c;使用自己制作的GO或KEGG背景文件进行富集分…

QT linux下应用程序打包

一、应用程序app 1、应用程序的pro文件 2、 程序工作函数 3、app的UI界面 二、动态库lib 1、Lib类头文件 2、.cpp文件 三、对应用程序和动态库进行构建 1、对动态库进行qmake,然后进行构建 2、对应用程序进行qmake&#xff0c;然后进行构建 3、查看构建目录 四、编写脚本 …

一键删除多余内容,批量处理HTML文本,轻松省时!

亲爱的用户们&#xff0c;您是否曾经为了删除HTML文本中的多余内容而烦恼&#xff1f;是否曾经为了批量处理文本而感到困扰&#xff1f;现在&#xff0c;我们为您带来了一款全新的HTML文本处理工具&#xff0c;它可以轻松解决您的问题&#xff01; 首先&#xff0c;在首助编辑…

【python】python基础速通系列2-python程序中的积木块

【组成Python的几个单位】 变量:指向值的名称。或者说变量是一个名称,这个名称指向一个具体的指。比如n=17,就说这个叫做n的变量的值是17。表达式:是值,变量和运算符的组合。如果把变量理解为名词,那么表达式就是把名词连起来的动词形容词。比如:n+25。语句:代码的基本…

Ansys Lumerical|带 1D-2D 光栅的出瞳扩展器

附件下载 联系工作人员获取附件 此示例显示了设置和模拟出瞳扩展器 &#xff08;EPE&#xff09; 的工作流程&#xff0c;EPE 是波导型增强现实 &#xff08;AR&#xff09; 设备的重要组成部分。该工作流程将利用 Lumerical 和 Zemax OpticStudio 之间的动态链接功能 。为了…