Spring Cloud之Seata的学习

目录

案例准备

分布式事务

基本理论

CAP定理

BASE理论

Seata

部署TC服务

数据库准备

修改Nacos配置并导入信息

启动Seata

集成Seata

XA模式原理

Seata的XA实现

优点

缺点

实现

AT模式原理

AT模式的脏写问题

Seata的AT实现

XA与AT的区别

TCC模式原理

空回滚与业务悬挂问题

Seata的TCC实现

Saga模式原理

四种模式对比

高可用


案例资料下载地址:day02分布式事务

案例准备

  1. 将资料中的seata-demo.sql文件加载到数据库中。
  2. seata-demo文件夹使用IDEA打开。
  3. 启动nacos与所有微服务
  4. 测试订单,发送POST请求

观察数据库

成功添加一个订单。

分布式事务

在分布式系统下,一个业务跨越多个服务或数据源,每个服务都是一个分支事务。要保证所有的分支事务最终状态保持一致,这样的事务就是分布式事务。

基本理论

CAP定理

所谓CAP是指:

  • Consistency(一致性)
  • Availability(可用性)
  • Partition tolerance(分区容错性)

分布式系统无法同时满足这三个指标。当分区出现时系统的一致性和可用性无法同时满足。

一致性:用户访问分布式系统中的任意节点,得到的数据必须一致

可用性:用户访问集群中任意健康节点,必须得到相应,而不是超时或拒绝

分区容错:所谓分区,就是因为网络故障或其它原因导致分布式系统中的部分节点与其它节点失去连接,形成独立分区。而容错,就是在集群出现分区时,整个系统也要持续对外提供服务

BASE理论

BASE理论是对CAP的一种解决思路

  • Basically Available(基本可用):分布式系统在出现故障时,允许损失部分可用性,即保证核心可用
  • Soft state(软状态):在一定时间内,允许出现中间状态,比如临时的不一致状态
  • Eventually Consistent(最终一致性):虽然无法保证强一致性,但是在软状态结束后,最终达到数据一致。

而分布式事务最大的问题是各个子事务的一致性问题,因此可以借鉴CAP定理和BASE理论:

  • AP模式:各子事务分别执行和提交,允许出现结果不一致,然后采用弥补措施恢复数据即可,实现最终一致。
  • CP模式:各个子事务执行后互相等待,同时提交,同时回滚,达成强一致。但事务等待过程中,处于弱可用状态。

比如ES集群就属于CP,当ES集群一个节点网络故障时,会被剔除,该节点的数据分片会被保存在其他节点上。保证了高一致性,低可用性。所以是CP。

Seata

Seata事务管理中存在三个角色:

  • TC(Transaction Coordinator)事务协调者:维护全局和分支事务的状态,协调全局事务提交或回滚
  • TM(Transaction Manager)事务管理器:定义全局事务的范围、开始全局事务、提交或回滚全局事务
  • RM(Resource Manager)资源管理器:管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。

Seata提供了四种不同的分布式事务解决方案:

  • XA模式:强一致性分阶段事务模式,牺牲了一定的可用性,无业务侵入
  • TCC模式:最终一致的分阶段事务模式,有业务侵入
  • AT模式:最终一致的分阶段事务模式,无业务侵入,也是Seata的默认模式
  • SAGA模式:长事务模式,有业务侵入

部署TC服务

下载Seata:GitHub - seata/seata: :fire: Seata is an easy-to-use, high-performance, open source distributed transaction solution.

需要注意的是,最新版本与1.5.0之前的Seata配置方式不同,这里我采用的是1.7.1版本。资料中的版本也有对应的文本文件。

数据库准备

sql文件保存在该目录下\script\server\db。在数据库中执行sql文件。

修改Nacos配置并导入信息

修改文件\seata\conf\application.yml

在Nacos创建配置文件

将路径\script\config-center\config.txt修改如下内容后全选粘贴到nacos中的配置内容处

启动Seata

双击启动bin目录下的seata-server.bat

访问地址http://localhost:7091/#/login

默认用户名与密码都为seata

nacos控制台可以看到seata的节点

集成Seata

引入依赖

        <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId><exclusions><exclusion><groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId></exclusion></exclusions></dependency><dependency><groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId><version>1.4.2</version></dependency>

配置文件添加如下内容

seata:registry:# nacos配置type: nacosnacos:application: seata-serverserver-addr: 127.0.0.1:8848group: DEFAULT_GROUPnamespace: seata-demousername: nacospassword: nacostx-service-group: seata-demo #事务组名称#如果seata是一个集群,那么在nacos寻找seata节点时,就要这么去配置service:vgroup-mapping: #事务组与cluster的映射关系seata-demo: SH

seata客户端发现seata集群中的节点,需要tx-service-group中的值作为key,vgroup-mapping作为value的映射关系去寻找。

XA模式原理

是强一致性的事务。基于数据库本身特性实现的

Seata的XA实现

RM一阶段的工作:

  • 注册分支事务到TC
  • 执行分支业务sql但不提交
  • 报告执行状态到TC

TC二阶段的工作:

  • TC检测各分支事务执行状态
    • 如果都成功,通知所有RM提交事务
    • 如果有失败,通知所有RM回滚事务

RM二阶段的工作:

  • 接收TC指令,提交或回滚事务
优点
  • 强一致性
  • 基于数据库做了一层封装,实现简单
缺点
  • 如果关联的事务较多,且耗时较长,已经执行完毕的事务还需要等待其他事务完成,耗费资源更大,性能差。
  • 依赖关系数据库实现,如果使用Redis则不适用
实现

修改配置文件。该配置作用是对数据源做代理,拦截所有sql请求,RM帮我们调用数据库的XA接口。

seata:data-source-proxy-mode: XA

给全局事务的入口方法添加注解@GlobalTransactional注解(和Transactional注解添加位置一样)

@GlobalTransactional
public Long create(Order order) {// 创建订单orderMapper.insert(order);try {// 扣用户余额accountClient.deduct(order.getUserId(), order.getMoney());// 扣库存storageClient.deduct(order.getCommodityCode(), order.getCount());} catch (FeignException e) {log.error("下单失败,原因:{}", e.contentUTF8(), e);throw new RuntimeException(e.contentUTF8(), e);}return order.getId();
}

接下来测试一个一定失败的新增订单请求

查看数据库发现,库存没有减少,用户金额也没扣减,订单也没增加。观察控制台输出,是扣款之后再回滚

AT模式原理

AT模式同样是分阶段提交事务模型。不过弥补了XA模型中资源锁定周期过长的缺陷。

阶段一RM工作:

  • 注册分支事务
  • 记录undo-log(快照)
  • 执行sql并提交
  • 报告事务状态

阶段二提交时RM的工作:删除undo-log

阶段二回滚时RM的工作:根据undo-log恢复数据到更新前

AT模式的脏写问题

出现脏写的情况是因为事务没有做到隔离,为了解决这个问题,引入了全局锁概念。TC记录当前正在操作某行数据的事务,该事务持有全局锁,具有执行权。主要记录的是事务id、事务操作的表名、以及该表的被修改的数据主键值。

需要注意的是。这里存在两个锁,一个是数据库的DB锁一个是Seata管理的全局锁。为了避免死锁问题,通常全局锁在等待300毫秒内还没有获取到锁就进行超时回滚。比DB锁超时时间要短很多。

由于全局锁只会对被Seata管理的事务生效,对普通事务不生效。因此,可能存在普通事务修改数据的可能,导致Seata管理的事务进行回滚时造成的脏写事件。对此,AT模式不光会保存修改前的数据快照(before-image),也会保存修改后的数据快照(after-image)。当进行回滚时,会对数据库当前的数据与修改后的数据库快照(after-image)进行对比。如果发现不一样,则说明在回滚之前期间有其他事务修改了数据。

Seata的AT实现

将资料中的seata-at.sql文件以文本方式打开。里面有两张表的创建语句。将lock_table表(管理全局锁的表)创建语句在TC服务的数据库中执行。undo_log表(快照存放表,由RM管理)在微服务访问的数据库中创建。

修改配置文件中的事务模式为AT

seata:data-source-proxy-mode: AT

重启服务后,发送一次库存不足的请求观察是否扣减余额和创建订单。

可以看到,执行了扣款操作,但是根据快照回滚并将快照信息删除。

XA与AT的区别

XA模式一阶段不提交事务,锁定资源;AT模式一阶段直接提交,不锁定资源

XA模式依赖数据库机制实现回滚;AT模式利用数据快照实现数据回滚

XA模式强一致;AT模式最终一致

TCC模式原理

TCC模式与AT模式非常相似,每阶段都是独立事务,不同的是TCC通过人工编码来实现数据恢复。需要实现三个方法:

  • Try:资源的检测和预留
  • Confirm:完成资源操作业务;要求Try 成功 Confirm 一定要能成功。
  • Cancel:预留资源释放,可以理解为try的反向操作。

阶段一进行资源预留。阶段二不管是提交还是回滚,都是对自己预留部分的操作。不需要像XA模式加锁或是AT模式一样保存数据快照。在性能上比前两种模式更好一些。

TCC模式的优点:

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

TCC模式的缺点:

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

空回滚与业务悬挂问题

当某分支事务的try阶段阻塞时,可能导致全局事务超时而触发二阶段的cancel操作。在未执行try操作时先执行了cancel操作,这时cancel不能做回滚,就是空回滚。

而对于已经空回滚的业务,如果后续阻塞的事务恢复,继续执行try,就永远不可能confire或cancel,这就是业务悬挂。应当阻止执行空回滚后的try操作,避免悬挂。

Seata的TCC实现

TCC实现资源冻结通常是新加一张表,被冻结的资源放在该表中,根据该表信息来执行Cancel

Try业务:

  • 记录冻结金额和事务状态到account_freeze表
  • 扣减account表可用金额

Confirm业务:根据xid删除account_freeze表的冻结记录

Cancel业务:

  • 修改account_freeze表冻结金额为0,state为2
  • 修改account表,恢复可用金额

如何判断是否空回滚:cancel业务中,根据xid查询account_freeze,如果为null则说明try还没做,需要空回滚。

如何避免业务悬挂:try业务中,根据xid查询account_freeze ,如果已经存在则证明Cancel已经执行,拒绝执行try业务

将资料中的account_freeze_tbl.sql文件在微服务访问的数据库执行。

编写Java业务代码

@LocalTCC
public interface AccountTCCService {//该注解在哪个方法上就说明哪个方法为try方法,name值要和方法名一样@TwoPhaseBusinessAction(name="deduct",commitMethod = "confirm",rollbackMethod = "cancel")void deduct(@BusinessActionContextParameter(paramName = "userId") String userId,//参数中的注解会被加载到BusinessActionContext中。@BusinessActionContextParameter(paramName = "money") int money);boolean confirm(BusinessActionContext ctx);boolean cancel(BusinessActionContext ctx);
}
@Service
public class AccountTCCServiceImpl implements AccountTCCService {@Autowiredprivate AccountMapper accountMapper;@Autowiredprivate AccountFreezeMapper accountFreezeMapper;@Overridepublic void deduct(String userId, int money) {//获取全局事务IDString xid = RootContext.getXID();AccountFreeze accountFreeze = accountFreezeMapper.selectById(xid);if (accountFreeze!=null){//已经执行过Cancel,不去执行return;}//扣减用户余额accountMapper.deduct(userId, money);//冻结表新增余额accountFreeze = new AccountFreeze();accountFreeze.setXid(xid);accountFreeze.setUserId(userId);accountFreeze.setFreezeMoney(money);accountFreeze.setState(AccountFreeze.State.TRY);accountFreezeMapper.insert(accountFreeze);}@Overridepublic boolean confirm(BusinessActionContext ctx) {//提交事务,删除该表全局事务对应的数据就可以String xid = ctx.getXid();int count = accountFreezeMapper.deleteById(xid);return count == 1;}@Overridepublic boolean cancel(BusinessActionContext ctx) {//判断是否为空回滚String xid = ctx.getXid();String userId = ctx.getActionContext("userId").toString();int money = (int) ctx.getActionContext("money");AccountFreeze accountFreeze = accountFreezeMapper.selectById(xid);if (accountFreeze == null) {//是空回滚accountFreeze = new AccountFreeze();accountFreeze.setXid(xid);accountFreeze.setUserId(userId);accountFreeze.setFreezeMoney(money);accountFreeze.setState(AccountFreeze.State.CANCEL);accountFreezeMapper.insert(accountFreeze);return true;}// 幂等处理if (accountFreeze.getState() == AccountFreeze.State.CANCEL) {return true;}//说明不是空回滚,恢复数据accountMapper.refund(userId, money);accountFreeze.setState(AccountFreeze.State.CANCEL);accountFreeze.setFreezeMoney(0);int count = accountFreezeMapper.updateById(accountFreeze);return count == 1;}
}

修改Controller代码,装配TCCService的bean对象。重启服务,再次发送一次库存不足请求

Saga模式原理

Saga模式是Seata提供的长事务解决方案。也分为两个阶段

一阶段:直接提交本地事务

二阶段:成功什么也不用做,失败通过编写补偿业务进行回滚

由于TCC是通过预留资源实现业务提交或回滚,而Saga是直接对资源本身进行操作,因此不存在事务隔离性,有一定安全问题。

优点:

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

缺点:

  • 软状态持续时间不确定,时效性差
  • 没有锁,没有事务隔离,会存在脏写问题

通常不适用该模式,通常使用AT模式,使用TCC或XA做补充

四种模式对比

XA

AT

TCC

SAGA

一致性

强一致

弱一致

弱一致

最终一致

隔离性

完全隔离

基于全局锁隔离

基于资源预留隔离

无隔离

代码入侵

要编写三个接口

要编写状态机和补偿业务

性能

很好

很好

场景

对一致性、隔离性有高要求的业务

基于关系型数据库的大多数分布式场景都可以

对性能要求较高的事务。有非关系型数据库要参与的事务

业务流程长,业务流程多。参与者包含其他公司或遗留系统服务,无法提供TCC模式要求的三个接口

高可用

TC服务作为Seata的核心服务,一定要保证高可用和异地容灾。接下来我们对Seata进行集群配置

将原来seata文件复制一份作为第二个节点

修改第二份文件集群名称。

接着启动2号节点

seata-server.bat -p 8092

接下来,我们需要将tx-service-group与cluster的映射关系都配置到nacos配置中心,方便生产环境下实现热更新部署。

微服务读取nacos配置文件

seata:config:type: nacosnacos:server-addr: 127.0.0.1:8848username: nacospassword: nacosgroup: SEATA_GROUPdata-id: client.properties

启动微服务观察

所有服务都注册到SH集群节点上。

修改nacos中的配置信息

实现了动态切换集群

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

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

相关文章

有人物联网模块连接阿里云物联网平台的方法

摘要&#xff1a;本文介绍有人物联网模块M100连接阿里云的参数设置&#xff0c;作为说明书的补充。 没有阿里云功能需求的请略过本文&#xff0c;不要浪费您宝贵的时间。 网络选择LTE&#xff0c;请先确保插入的SIM卡有流量。 接下来配置阿里云云服务。如下图所示&#xff0c;…

windows mysql安装

1、首先去官网下载mysql安装包&#xff0c;官网地址&#xff1a;MySQL :: Download MySQL Community Server 2&#xff1a;把安装包放到你安装mysql的地方&#xff0c;然后进行解压缩&#xff0c;注意&#xff0c;解压后的mysql没有配置文件&#xff0c;我们需要创建配置文件 配…

mediasoup webrtc音视频会议搭建

环境ubuntu22.10 nvm --version 0.33.11 node -v v16.20.2 npm -v 8.19.4 node-gyp -v v10.0.1 python3 --version Python 3.10.7 python with pip: sudo apt install python3-pip gcc&g version 12.2.0 (Ubuntu 12.2.0-3ubuntu1) Make 4.2.1 npm install mediasoup3 sudo …

S4.2.4.7 Start of Data Stream Ordered Set (SDS)

一 本章节主讲知识点 1.1 xxx 1.2 sss 1.3 ddd 二 本章节原文翻译 2.1 SDS 数据流开始有序集 SDS 代表传输的数据类型从有序集转为数据流。它会在 Configuration.Idle&#xff0c;Recovery.Idle 和 Tx 的 L0s.FTS 状态发送。Loopback 模式下&#xff0c;主机允许发送 SDS。…

初阶JavaEE(14)表白墙程序

接上次博客&#xff1a;初阶JavaEE&#xff08;13&#xff09;&#xff08;安装、配置&#xff1a;Smart Tomcat&#xff1b;访问出错怎么办&#xff1f;Servlet初识、调试、运行&#xff1b;HttpServlet&#xff1a;HttpServlet&#xff1b;HttpServletResponse&#xff09;-C…

Rust学习日记(二)变量的使用--结合--温度换算/斐波那契数列--实例

前言&#xff1a; 这是一个系列的学习笔记&#xff0c;会将笔者学习Rust语言的心得记录。 当然&#xff0c;这并非是流水账似的记录&#xff0c;而是结合实际程序项目的记录&#xff0c;如果你也对Rust感兴趣&#xff0c;那么我们可以一起交流探讨&#xff0c;使用Rust来构建程…

修复dinput8.dll文件的缺失,以及修复dinput8.dll文件时需要注意什么

dinput8.dll文件通常在使用大型游戏时容易出现dinput8.dll文件丢失的情况&#xff0c;今天这篇文章将要教大家修复dinput8.dll文件的缺失&#xff0c;同时在修复dinput8.dll文件时需要注意些什么&#xff1f;防止文件在修复的过程中出现其他的错误。 dinput8.dll是DirectInput库…

HarmonyOS列表组件

List组件的使用 import router from ohos.routerEntry Component struct Index {private arr: number[] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]build() {Row() {Column() {List({ space: 10 }) {ForEach(this.arr, (item: number) > {ListItem() {Text(${item}).width(100%).heig…

SQL Server2000mdf升级SQL Server2005数据库还原

SQL Server2000数据库还原sqlserver 2000mdf升级 sqlserver 2008数据库还原SQL Server2005数据库脚本 sqlserver数据库低版本升级成高版本 sqlserver数据库版本升级 数据库版本还原 如果本机安装了sqlserver2012或者sqlserver2019等高版本 怎么样才能运行sqlserver2000的数据库…

Make.com实现多个APP应用的自动化的入门指南

Make.com是一款基于云的自动化平台&#xff0c;可帮助用户将多个应用程序连接在一起&#xff0c;并通过设置自动化流程来简化日常任务。Make.com提供丰富的API集成&#xff0c;支持连接各种流行的应用程序&#xff0c;包括社交媒体、电子商务、CRM等。 使用Make.com实现多个AP…

基于8086家具门安全控制系统设计

**单片机设计介绍&#xff0c;基于8086家具门安全控制系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 # 8086家具门安全控制系统设计介绍 8086家具门安全控制系统是一种用于保护家具和保证室内安全的系统。该系统基于808…

从0到1:腾讯云服务器使用教程

腾讯云服务器入门教程包括云服务器CPU内存带宽配置选择&#xff0c;选择云服务器CVM或轻量应用服务器&#xff0c;云服务器创建后重置密码、远程连接、搭建程序环境等&#xff0c;腾讯云服务器网txyfwq.com分享从0到1腾讯云服务器入门教程&#xff1a; 目录 腾讯云服务器入门…

6 从物理层到MAC层

1、实现局域网中玩游戏 在早期的80后的大学宿舍中&#xff0c;组件一个宿舍的局域网&#xff0c;以便于宿舍内部可以玩游戏. 第一层&#xff08;物理层&#xff09; 1.首先是实现电脑连接电脑&#xff0c;需要依靠网线&#xff0c;有两个头。 2.一头插在一台电脑的网卡上&am…

WebGL:基础练习 / 简单学习 / demo / canvas3D

一、前置内容 canvas&#xff1a;理解canvas / 基础使用 / 实用demo-CSDN博客 WebGL&#xff1a;开始学习 / 理解 WebGL / WebGL 需要掌握哪些知识 / 应用领域 / 前端值得学WebGL吗_webgl培训-CSDN博客 二、在线运行HTML 用来运行WebGL代码&#xff0c;粘贴--运行&#xff…

大数据毕业设计选题推荐-无线网络大数据平台-Hadoop-Spark-Hive

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…

无需使用jadx-gui和mac电脑获取app备案公钥的方法

由于2023年&#xff0c;国家要求上架的app必须备案&#xff0c;因此app备案成为了很多公司迫切的需求。 备案的时候&#xff0c;需要填写app公钥&#xff0c;MD5值等参数&#xff0c;这些参数对于不熟悉加密技术的人来说&#xff0c;简直是无从下手&#xff0c;因为目前的开发…

LangChain+LLM实战---实用Prompt工程讲解

原文&#xff1a;Practical Prompt Engineering 注&#xff1a;本文中&#xff0c;提示和prompt几乎是等效的。 这是一篇非常全面介绍Prompt的文章&#xff0c;包括prompt作用于大模型的一些内在机制&#xff0c;和prompt可以如何对大模型进行“微调”。讲清楚了我们常常听到的…

flink状态不能跨算子

背景 在flink中进行状态的维护和管理应该是我们经常做的事情&#xff0c;但是有些同学认为名称一样的状态在不同算子之间的状态是同一个&#xff0c;事实是这样吗&#xff1f; flink状态在保存点中的存放示意图 事实上&#xff0c;每个状态都归属于对应的算子&#xff0c;也…

thinkphp漏洞复现

thinkphp漏洞复现 ThinkPHP 2.x 任意代码执行漏洞Thinkphp5 5.0.22/5.1.29 远程代码执行ThinkPHP5 5.0.23 远程代码执行ThinkPHP5 SQL Injection Vulnerability && Sensitive Information Disclosure VulnerabilityThinkPHP Lang Local File Inclusion ThinkPHP 2.x 任…

xlua源码分析(二)lua Call C#的无wrap实现

xlua源码分析&#xff08;二&#xff09;lua Call C#的无wrap实现 上一节我们主要分析了xlua中C# Call lua的实现思路&#xff0c;本节我们将根据Examples 03_UIEvent&#xff0c;分析lua Call C#的底层实现。例子场景里有一个简单的UI面板&#xff0c;面板中包含一个input fie…