分布式事务-SpringBoot集成Seata

news2024/11/22 16:32:56

1.本地事务和分布式事务概念

事务四大特性

  • 原子性:事务不可再分
  • 一致性:数据改变前后,总量必须一致
  • 隔离性:事务之间相互隔离,互不干扰
  • 持久性:事务一旦提交,数据就会持久化到磁盘,不能回滚

本地事务:所有的事务都是基于数据库的,那么我们在代码中加@Transactional其实是使用的数据库的Begin/Commit/Rollback,底层使用的是动态代理。本地事务只能管理到当前服务连接的那个数据库的事务,如果一个事务中操作了多个数据库在回顾的时候只能回滚当前服务连接的那个数据库,没办法回滚其它数据库

分布式事务:用于解决在一个方法中操作多个数据库的事务,分布式事务其实就是将多个数据库加入到同一组事务中,当某一个数据库发生异常时整体回滚

2.分布式事务的解决方案

2.1 XA协议

  • 简单理解就是XA规范协议是一种事务协议,通过这种协议来通知数据库事务的开始、结束、提交、以及回滚,XA 接口函数由数据库厂商提供。XA协议使用二阶段提交来处理分布式事务,说的更明白一点就是XA协议保证了分布式事务的原子性,要么都成功,要么都失败。
  • XA协议采用两阶段提交方式来管理分布式事务

2.2 2PC模式

2PC就是基于XA协议进行实现的,采用两阶段提交 2PC(Two Phase Commitment Protocol)来管理分布式事务,所谓二阶段是有两个阶段组成,一阶段投票阶段和二阶段提交阶段。同时它是由“事务协调器”和若干“事务执行者”两个角色组成。

第一阶段:准备阶段( 投票阶段 )

  1. 事务协调器向所有事务参与者发请求,询问是否可以执行提交操作(你们都可以执行事务操作吗?),并开始等待各参与者节点的响应。
  2. 事务参与者收到协调者的指令开始执行事务操作但是不会提交事务,同时写Undo log(写操作之前首先将数据备份log,如果要回滚就从这个log进行数据还原) 和 Redo log(修改数据在buffer pool缓冲池中修改,Redo log是对这个缓冲池的内容做持久,避免修改的数据丢失) 。
  3. 如果参与者事务操作都执行成功(注意哦,没提交事务哦),那么就会回复 事务协调器 “准备OK” ,如果事务操作失败,那么就会回复执行者“准备不OK”。

第二阶段:提交阶段

正常流程

  1. 事务协调器会收到参与者的回复,如果所有的参与者都回复“准备ok”,意味着所有的参与者都可以完成事务操作,那么事务协调器会向每个事务参与者发送一个“commit” 提交事务指令(既然大家都可以进行事务操作,那大家都提交事务把)
  2. 事务参与者收到指令就开始提交事务,然后会向事务协调器回复“完成”,事务协调器收到所有参与者都回复完成,事务完成

回滚流程

  1. 如果再第一阶段事务协调器收到了某个事务参与者回复“准备不ok”即事务操作执行失败,那么事务协调器会向所有的事务参与者发送“rollback”回滚执行(有一个成员不ok,那大家都散了吧,今天的事情搞不成了)
  2. 事务参与者收到指令,回滚之前的事务操作,即:将数据还原到“Undo log”的数据,然后向事务协调者回复“回滚成功”,当事务协调器收到所有的参与者回复“回滚成功”后,取消事务。

发送回滚指令

二阶段提交的问题

  • 二阶段能保证分布式事务的原子性,但是也有一些明显的缺陷。比如:在第一阶段,如果参与者迟迟不回复协调者,就会造成事务的阻塞,性能不好。
  • 单节点故障,如果协调器挂了,参与者会阻塞,比如在第二阶段,如果事务协调器宕机,参与者没办法回复信息,长时间处于事务资源锁定,造成阻塞(事务操作是要加锁的)。
  • 在第二阶段,如果在事务协调器发出"commit"执行后宕机,一部和参与者收到了消息提交了事务,而一部分没有消息没法做出事务提交操作,这样就出现了数据不一致。
  • 在第二阶段,如果事务事务协调器发出“commit”指令后宕机,收到“commmit”指令的参与者也宕机了,那么事务最终变成了什么效果,提交了还是没提交?没有谁知道。

2.3 3PC模式

三阶段提交(Three-phase commit),也叫三阶段提交协议(Three-phase commit protocol),是二阶段提交(2PC)的改进版本,

3PC在2PC的功能上做了两个改动,一是在协调者和事务参与者之间引入了超时机制,在第一阶段和第二阶段中插入一个准备阶段 , 保证了在最后提交阶段之前各参与节点的状态是一致的,那么现在的三阶段分为了:

  1. canCommit“询问是否能提交,
  2. papreCommit”准备提交阶段 ,
  3. doCommit”提交阶段。

第一阶段“canCommit” :

  1. 事务协调者向事务参与者发送 canCommit 请求询问是否能提交事务,然后等待所有事务参与者的返回
  2. 事务参与者接收到事务些调整的canCommit指令,然后自身认为能够提交事务则返回 “yes”否则返回“no”

第二阶段“papreCommit”

事务协调者收到所有的事务参与者的canCmmit指令的反馈结果,这里有两种情况,一是所有的反馈都是yes,二是有部分的事 务参与者返回No,后者反馈超时。

正常流程

  1. 如果事务协调者收到所有的事务参与者的canCmmit指令反馈结果都为YES,那么就进入papreCommit阶段。事务协调者向事务参与者发送 “papreCommit”指令。
  2. 事务参与者收到“papreCommit”指令,开始进行事务操作,并将undo和redo信息记录到事务日志中,如果顺利执行事务操作,则反馈ACK确认信息,然后等待下一步指令。

中断事务

  1. 如果事务协调者收到所有的事务参与者的canCmmit指令反馈结果出现了NO,或者等待超时,那么就执行事务中断,向所有的事务参与者发送“abort”中断指令。
  2. 事务参与者接收到“abort”指令,中断事务,当然如果事务参与者迟迟未收到事务协调者的指令等待超时也会中断事务。

第三阶段“doCommit阶段”

这里准备提交事务了,这里有两种情况,如果事务协调者收到所有的事务参与者的papreCommit指令反馈结果都是ACK,那么进入doCommit阶段,否则会中断事务。

正常流程

  1. 事务协调者收到所有的事务参与者的papreCommit指令反馈结果都是ACK,然后向事务参与者发送“doCommit”指令,通知提交事务。
  2. 事务参与者收到“doCommit”指令,正式执行事务提交,并且释放所有事务资源,返回向事务协调者返回事务结果状态“ACK”完成
  3. 事务协调者收到所有的事务参与者都返回ACK成功,完成事务。

中断事务

  1. 事务协调者收到的事务参与者的papreCommit指令反馈结果有的不是ACK,那么事务协调者然后向事务参与者发送“abort”事务中断指密令。
  2. 事务参与者收到“abort”事务指令,会根据unlog日志文件还原数据,然后释放事务资源,然后向事务协调者发送回滚“ACK”消息
  3. 事务协调者收到所有的事务参与者都返回ACK消息,取消事务。

2.4 TCC事物补偿

TCC(Try Confirm Cancel) 事务补偿机制,即每一个操作都要做相应的补偿机制,即如何确认操作成功,如果操作失败如何撤销事务。它分为三个阶段

  1. Try : try的意思是尝试,其实这个步骤是用来做业务的预处理,可以理解为是做一些准备工作,等到Confirm之后这些操作才算成功。
  2. Confirm :确认,如果所有的事务参与者都try成功,执行commit对业务做提交操作,或者可以理解成对try的工作作出确认。
  3. Cancel:取消,如果try失败需要回滚,即取消try的预处理操作

2.5 MQ消息最终一致性

大致流程是:

1.主业务方向发送一个“Prepared”准备消息到MQ,这个消息还未被确认,不会发生给消费者,然后MQ向生产者发送确认收到消息,然后主业务方执行自己的业务,并提交本地事务,成功后向MQ确认之前的“Prepared”消息发生给消费者,如果失败MQ将当前半消息删除,取消事务。

2.消息接受者方收到消息后执行业务逻辑,提交本地事务,然后向MQ返回ACK确认消息,如果ACK消息为成功,MQ则删除当前消息;如果消费者消息接受失败或返回ACK是失败,会进行重试,保证消息最终被消费。直到16次后还是失败,消息会进入死信队列,该消息不会被删除,也不会重发,需要人工介入;

RocketMQ的事务消息:使用MQ的分布式事务是最终一致性

  1. 生成者发送一个半事务消息给MQ,MQ告诉生产者接收到了,此时生产者方就去执行本地事务
  2. 如果执行成功那么告诉MQ执行Commit,如果本地事务失败MQ执行Rollback。那么MQ执行Commit就是把此消息发送给消费者,消费者接收到消息之后执行本地事务,如果执行成功那么响应ACK确认成功,如果执行失败那么响应ACK失败,MQ接收到成功删除此消息,如果失败那么会再次发送,直到16次之后还是失败那么进入到死信队列,此时就需要我们人工去检查代码手动发送消息再次消费。如果MQ执行Rollback那么就会把此消息进行删除。
  3. 如果避免生产者一直不提交commit或rollback还准备了一个回查机制,调用我们写的一个方法,在方法中去检查生产者的本地事务是否执行成功,如果成功提交commit,如果失败提交rollback

2.6 Seata框架

seata(Simple Extensible Autonomous Transaction Architecture) 是 阿里巴巴开源的分布式事务中间件,致力于提供高性能,零入侵和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。

Seata 的设计思路是将一个分布式事务可以理解成一个全局事务,下面挂了若干个分支事务,而一个分支事务是一个满足 ACID 的本地事务,因此我们可以操作分布式事务像操作本地事务一样。

Seata重要组成

  • Transcation ID(XID) : 由事务协调者创建的全局唯一的事务ID
  • Transaction Coordinator(TC) - 事务协调器:一个独立运行的组件,负责维护全局事务的运行状态,负责根据TM的指令协调并驱动全局事务的提交或回滚,负责向资源管理器发起事务提交,回滚指令。
  • Transaction Manager - 事务管理器 :控制全局事务的边界,负责开启一个全局事务,并最终发起全局提交或全局回滚的决议,通知TC提交或者回滚事务。
  • Resource Manager(RM) - 资源管理器: 控制分支事务,负责分支事务注册、负责向TC汇报分支事务状态,并接收事务协调器的指令,驱动分支(本地)事务的提交和回滚

正常执行流程:

  1. 系统启动TM事务管理者以及RM资源管理者需要向事务协调器进行提交注册,可以看做是一种初始化。
  2. 在Bussiness的业务主方法上我们需要打上@GlobalTransationl注解,通过这个注解,事务管理器TM向事务协调者(TC)申请开启一个全局分布式事务,事务协调者创建全局事务后返回全局唯一的 XID,这个XID 会在涉及微服务的整个全局事务的上下文中进行传播。
  3. 业务开始,Bussiness通过Feign调用Order,并传递全局事务XID,Order在做写操作的时候,RM资源管理器 (Order集成了RM)向事务 协调器TC 注册本地分支事务,该分支事务归属于拥有相同 XID 的全局事务,同时事务协调者TC会返回一个分支事务ID:“branchId” 。说明一下:Seate通过代理DataSource向TC发起分子事务注册的。
  4. 这个时候Order会正常的写数据库,然后会写入一个undo log(这个日志文件记录了数据库修改前的数据,用来做回滚),然后提交分支事务(注意,分支事务已经提交了) , 最后向TC上报事务处理状态。当然Account做的事情和Order是相同的。
  5. Order和Account都调用完成,代码回到Business,这时TM事务管理器向TC事务协调者发起全局事务提交请求,TC向RM事务分支发起事务提交请求,RM(Order, Account)直接删除到undo log日志文件即可,因为之前已经提交了本地事务

异常执行流程:

前面2个步骤都跟上面一样,这里省略 , 在第 3 步的时候,Order在可能因为某种原因本地分支事务提交失败了,那么RM会向TC上报一个失败的事务状态

在第 4 步 ,这个时候代码回到Business,这时TM事务管理器会向TC事务协调者发起全局事务回滚请求,TC向RM事务分支发起事务回滚请求,RM(Order, Account)收到回滚指令,然后会解析undo log,指向反向操作,把数据还原到修改之前,删除undo log,提交本地事务。

3.微服务整合seata

3.1导入依赖
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
3.2yaml配置seata

项目的yaml中对seata做配置

  • 这里的tx-service-group: ${spring.application.name}-tx-group要和seataServer.properties中的保持一致
seata:
  enabled: true
  application-id: ${spring.application.name}
  tx-service-group: ${spring.application.name}-tx-group #it-fccar-service-driver-tx-group
  #对应seataServer.properties中的service.vgroupMapping.it-drive-service-driver-tx-group=default
  config:
    type: nacos
    nacos:
      server-addr: ${NACOS_HOST:8.137.85.173:8848}:${NACOS_PORT:8848}
      username: nacos
      password: nacos #账号再nacos管理界面配置
      namespace: fccar-dev #取pom.xml中的命名空间
      data-id: seataServer.properties
      group: DEFAULT_GROUP #重要,和seataServer.properties保持一样
  registry:
    type: nacos
    nacos:
      application: service-seata #seata的服务名
      server-addr: ${NACOS_HOST:8.137.85.173:8848}:${NACOS_PORT:8848}
      username: nacos
      password: nacos #账号再nacos管理界面配置
      namespace: fccar-dev #取pom.xml中的命名空间
      group: DEFAULT_GROUP
  enable-auto-data-source-proxy: true #开启seata的datasource自动代理

在启动类贴注解开启seata , 因为yaml做了配置,下面注解可以不要

@EnableAutoDataSourceProxy(dataSourceProxyMode="AT",useJdkProxy=false)
3.3.开启全局事务

开启全局事务,在入口方法贴注解

  • 注意:只在业务入口的微服务的方法上贴即可
@GlobalTransactional(name = "driver-wechat-register",rollbackFor = Exception.class)

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

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

相关文章

win10 wsl2 install

安装 迁移 docker WSL2常用指令 在 WSL2 中推出或关闭 WSL 实例&#xff0c;可以使用以下几种方法&#xff1a; 1. 使用 exit 命令 在 WSL2 终端中&#xff0c;输入以下命令即可退出当前的 WSL 会话&#xff1a; exit2. 使用 logout 命令 你也可以使用&#xff1a; l…

「Mac畅玩鸿蒙与硬件23」鸿蒙UI组件篇13 - 自定义组件的创建与使用

自定义组件可以帮助开发者实现复用性强、逻辑清晰的界面模块。通过自定义组件,鸿蒙应用能够提高代码的可维护性,并简化复杂布局的构建。本篇将介绍如何创建自定义组件,如何向组件传递数据,以及如何在不同页面间复用这些组件。 关键词 自定义组件复用组件属性传递组件通信组…

flutter 专题二 Flutter状态管理之Riverpod 0.8.4

一 、flutter 有哪些状态管理方式 Flutter的状态管理方式有很多&#xff0c;Redux、 Bloc、 MobX、Provider等等。单单一个Provider&#xff0c;我也见到了各种组合&#xff0c;例如ChangeNotifier Provider / StateNotifier Provider&#xff08; freezed&#xff09;。各…

uniapp编译多端项目App、小程序,input框键盘输入后

项目场景&#xff1a; uniapp编译后的小程序端&#xff0c;app端 在一个输入框 输入消息后&#xff0c;点击键盘上的操作按钮之后键盘不被收起&#xff0c;点击其他发送按钮时&#xff0c;键盘也不被收起。 问题描述 在编译后的app上普通的事件绑定&#xff0c;tap,click在发…

高并发编程

一台64G内存的服务器QPS可以达到9W&#xff0c;TPS&#xff08;事务&#xff09;可以达到5K&#xff0c;每个TPS大约包含18个QPS.只读的话QPS可以达到30~40万.阿里云有相关测试工具、测试方法、测试结果。 1、volatile 保证可见性&#xff0c;禁止指令重排&#xff0c;避免多线…

论文 | PROMPTAGATOR : FEW-SHOT DENSE RETRIEVAL FROM 8 EXAMPLES

1. 背景信息 在信息检索领域&#xff0c;传统的方法往往依赖于大量的标注数据来训练模型&#xff0c;以便在各种任务中表现良好。然而&#xff0c;许多实际应用中的监督数据是有限的&#xff0c;尤其是在不同的检索任务中。最近的研究开始关注如何从一个拥有丰富监督数据的任务…

群控系统服务端开发模式-应用开发-上传工厂开发

现在的文件、图片等上传基本都在使用oss存储。而现在常用的oss存储有阿里云、腾讯云、七牛云、华为云等&#xff0c;但是用的最多的还是前三种。而我主要封装的是本地存储、阿里云存储、腾讯云存储、七牛云存储。废话不多说&#xff0c;直接上传设计图及说明&#xff0c;就一目…

STM32之串口字库更新

1.串口通讯介绍 串口通讯&#xff08;Serial Communications&#xff09;是一种通过串口进行数据传输的通讯方式&#xff0c;通过串行口每次传输一个字节的数据&#xff0c;按照约定的协议进行数据的传输和接收。串口通讯的原理是利用串行口的发送和接收线路&#xff0c;将需要…

立刻解决 gcc: error: unrecognized argument in option ‘-mabi=aapcs-linux’

unrecognized argument in option ‘-mabiaapcs-linux’ Linux 主线支持的硬件较少&#xff0c;一般是第三方开源&#xff08; Linaro/Yocto &#xff09;或者硬件厂商提供定制的嵌入式 Linux 如果确认主线支持自己的硬件&#xff0c;可以从 https://www.kernel.org/ 获取指定…

法律智能助手:开源NLP系统助力法律文件高效审查与检索

一、系统概述 思通数科AI平台是一款融合了自然语言处理和多标签分类技术的开源智能文档分类工具&#xff0c;特别适用于法律行业。平台采用深度学习的BERT模型来进行特征提取与关系抽取&#xff0c;实现了精准的文档分类和检索。用户可以在线训练和标注数据&#xff0c;使系统…

ChatGPT新体验:AI搜索功能与订阅支付指南

就在凌晨&#xff0c;在ChatGPT迎来两周岁生日之际&#xff0c;OpenAI重磅发布了ChatGPT的全新人工智能搜索体验。 期待已久的时刻终于到来&#xff0c; ChatGPT正式转型成为一款革命性的AI搜索引擎! 先来看看ChatGPT搜索&#xff1a;这次不是简单的加个搜索框&#xff0c;而…

【零售和消费品&家居用品】家庭门窗开闭状态安全监控系统源码&数据集全套:改进yolo11-DCNV2

改进yolo11-GhostDynamicConv等200全套创新点大全&#xff1a;家庭门窗开闭状态安全监控系统源码&#xff06;数据集全套 1.图片效果展示 项目来源 人工智能促进会 2024.11.01 注意&#xff1a;由于项目一直在更新迭代&#xff0c;上面“1.图片效果展示”和“2.视频效果展示”…

合并区间 leetcode56

合并区间leetcode 目录一、题目二、踩坑过程三、上官方解答四、含泪体会彩蛋 目录 一、题目 二、踩坑过程 一开始想使用一个数组来标记区间&#xff0c;但是仔细想不好实现&#xff0c;单纯把区间里出现的设置为1&#xff0c;不好体现重叠的概念&#xff0c;如果使用三种状态…

【Linux】- 权限

目录 一、Linux常用热键 &#xff08;1&#xff09;、history&#xff1a; &#xff08;2&#xff09;、单击tab键 / 双击tab键 &#xff08;3&#xff09;、快捷键ctrl c 和 ctrl d 二、关机指令 shutdown 三、window与linux互传文件 四、不同linux系统间互传文件 …

C++(友元、异常机制、静态成员、单例模式)

友元 友元可以访问与其好友关系的类中的私有成员&#xff0c;使用friend关键字进行修饰。&#xff08;友元破坏了类的封装性&#xff09;。 特点 &#xff08;1&#xff09;友元是单向的 &#xff08;2&#xff09;友元不能传递 &#xff08;3&#xff09;友元…

Halcon区域分割之分水岭分割法

现实中我们见到过有山有湖的景象&#xff0c;那么一定是水绕山、山围水的情形。当然可在需要的时候人工构筑分水岭&#xff0c;以防集水盆之间的互相穿透。而区分高山与水的界线以及湖与湖之间的间隔&#xff0c;就是分水岭。 分水岭分割法是一种基于拓扑理论的数学形态…

【python】OpenCV—Tracking(10.4)—Centroid

文章目录 1、任务描述2、人脸检测模型3、完整代码4、结果展示5、涉及到的库函数6、参考 1、任务描述 基于质心实现多目标&#xff08;以人脸为例&#xff09;跟踪 人脸检测采用深度学习的方法 核心步骤&#xff1a; 步骤#1&#xff1a;接受边界框坐标并计算质心 步骤#2&…

使用Jupyter Notebook进行数据科学项目

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 使用Jupyter Notebook进行数据科学项目 Jupyter Notebook 简介 安装 Jupyter Notebook 创建和管理 Notebook 编写和运行代码 示例…

MR30分布式IO:石化行业的智能化革新

在浩瀚的工业领域中&#xff0c;石化行业如同一座巨大的化工厂&#xff0c;将自然界的原始资源转化为人们日常生活中不可或缺的各种产品。然而&#xff0c;随着生产规模的扩大和工艺复杂度的提升&#xff0c;石化行业面临着前所未有的挑战&#xff1a;如何在保证生产效率的同时…

Android 使用ninja加速编译的方法

ninja的简介 随着Android版本的更迭,makefile体系逐渐增多,导致make单编模块的时间越来越长,每次都需要半个小时甚至更长时间,其原因为每次make都会重新加载所有mk文件,再生成ninja编译,此完整过程十分耗时,实际编译代码仅占其中的一小部分。 因此我们可以使用google提…