seata分布式事务解决方案
下载地址:Releases · seata/seata · GitHub
一、什么是分布式事务
首先这是普通事务:
下面是分布式事务:
在微服务系统中,每个微服务应用都可能会有自己的数据库,它们首先需要控制自己的本地事务。
一项业务操作可能会调用执行多个微服务。如何保证多个服务执行的多个数据库的操作整体成功或整体失败?这就是分布式事务要解决的问题。
二、Seata介绍
Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。
三、Seata AT
Seata 的 AT 模式(Automatic Transaction)是一种无侵入的分布式事务解决方案。
1、业务场景订单系统
当用户下订单时,执行以下三步流程:
- 订单系统保存订单
- 订单系统调用库存服务,减少商品库存
- 订单系统调用账户服务,扣减用户金额
这三步要作为一个整体事务进行管理,要么整体成功,要么整体失败。
2、Seata AT基本原理
Seata AT 事务分两个阶段来管理全局事务:
第一阶段: 执行各分支事务
第二阶段: 控制全局事务最终提交或回滚
第一阶段:执行各分支事务
微服务系统中,各服务之间无法相互感知事务是否执行成功,这时就需要一个专门的服务,来协调各个服务的运行状态。这个服务称为 TC(Transaction Coordinator),事务协调器。
订单系统开始执行保存订单之前,首先启动 TM(Transaction Manager,事务管理器),由 TM 向 TC 申请开启一个全局事务:
这时TC会产生一个全局事务ID,称为 XID,并将 XID 传回 TM:
这样就开启了全局事务!
全局事务开启后,开始执行创建订单的业务。首先执行保存订单,这时会先启动一个 RM(Resource Manager,资源管理器),并将 XID 传递给 RM。
RM 负责对分支事务(即微服务的本地事务)进行管理,并与 TC 通信,上报分支事务的执行状态、接收全局事务的提交或回滚指令。
RM 首先会使用 XID 向 TC 注册分支事务,将分支事务纳入对应的全局事务管辖。
现在可以执行保存订单的分支事务了。一旦分支事务执行成功,RM 会上报事务状态:
TC 收到后,会将该状态信息传递到 TM:
到此,保存订单过程结束。
相同的,完成其他模块分支事务:
第二阶段: 控制全局事务最终提交或回滚
全局事务最终提交
全局事务最终回滚
3、Seata AT具体工作机制
第一阶段:执行分支事务
以全面订单业务中的库存服务为例,库存表中存在一条商品的库存信息:
现在要执行业务操作减少库存,从50件减少到40件:
执行修改库存业务操作前, 会先取出旧的库存信息进行保存:
现在可以修改库存了:
接着,取出更新后的新数据:
接下来,会把旧数据和新数据合并起来,保存到一个事务回滚日志表:undo_log表:
至此,第一阶段,分支事务完成,将状态上报给TC:
第二阶段:控制全局事务最终提交或者最终回滚
全局事务最终提交
如果全局事务成功,要完成最终提交,AT模式最终提交操作非常简单,只需要删除日志数据即可。首先接收到 TC 的全局事务提交指令:
然后直接删除事务日志,就完成了第二阶段提交操作:
全局事务最终回滚
假如全局事务失败,那么第一阶段已提交的分支事务要执行回滚操作。首先会收到来自 TC 的全局事务回滚指令:
根据事务回滚日志(undo_log)表的记录,将商品恢复成旧的库存数据:
然后删除事务日志,最终完成第二阶段回滚操作:
4、简单理解工作机制
订单、库存、账户这三个模块数据相互关联,应当同时成功,当一个模块失败,需要3模块一起执行回滚,保证数据同步。
当模块向数据库执行更新操作,他会自动先执行查询语句,将该表存入日志,每个模块都做同样的事。当事务执行成功,删除日志。 当事务执行失败,执行集体回滚,将日志中的内容覆盖各自的表,然后散出日志记录。
5、seataAT配置步骤
1、修改下载的seata中的文件配置
registry.conf 向 eureka 注册
file.conf seata server运行过程中产生的日志数据,存储到什么位置
修改启动文件:
seata-server.bat
用文本编辑器打开文件,找到文件中这一行:
%JAVACMD% %JAVA_OPTS% -server -Xmx2048m -Xms2048m -Xmn1024m -Xss512k -XX:Sur......
看到 Seata Server 默认使用 2G 内存,测试环境我们可以把内存调低:%JAVACMD% %JAVA_OPTS% -server -Xmx256m -Xms256m -Xmn128m -Xss512k -XX:Sur......
2、运行 seata-server.bat 启动服务
在bin目录下输入启动命令:seata-server.bat
注意事项:
JAVA_HOME、PATH
JDK 必须用 1.8
命令行窗口不能关闭
窗口中内容不能选中,否则应用会被挂起,暂停执行
添加 Seata At 事务
3、AT项目中项目实战配置(调用和被调用都要添加)
Ⅰ、在需要管理的事务模块中添加 seata 依赖
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-seata</artifactId><version>${spring-cloud-alibaba-seata.version}</version><exclusions><exclusion><artifactId>seata-all</artifactId><groupId>io.seata</groupId></exclusion></exclusions></dependency><dependency><groupId>io.seata</groupId><artifactId>seata-all</artifactId><version>${seata.version}</version></dependency>
Ⅱ、application.yml 设置事务组的组名
spring cloud:alibaba:seata:tx-service-group: order_tx_group
Ⅲ、registry.conf 设置注册中心的地址
与seata中的registry.conf 文件相对应
Ⅳ、file.conf 事务组对应使用的协调器
同理
Ⅴ、新建自动配置类,创建数据源代理
数据源:数据源是指数据库应用程序所使用的数据库或者数据库服务器。数据源(Data Source)顾名思义,数据的来源,是提供某种所需要数据的器件或原始媒体。在数据源中存储了所有建立数据库连接的信息。就像通过指定文件名称可以在文件系统中找到文件一样,通过提供正确的数据源名称,你可以找到相应的数据库连接。
import com.zaxxer.hikari.HikariDataSource;
import io.seata.rm.datasource.DataSourceProxy;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;import javax.sql.DataSource;@Configuration
public class DSAutoConf {// 创建原始数据源@ConfigurationProperties(prefix = "spring.datasource") //配置文件中数据库连接配置@Beanpublic DataSource getDataSource() {return new HikariDataSource();}// 创建数据源代理@Primary // 由于上下两个名字冲突,该注解表示spring的首选对象@Beanpublic DataSource getDataSourceProxy(DataSource ds) {return new DataSourceProxy(ds);}
}
spring:application:name: orderdatasource:url: jdbc:mysql:///seata_order?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8driver-class-name: com.mysql.cj.jdbc.Driverusername: rootpassword: rootjdbcUrl: ${spring.datasource.url}
Ⅵ、、在业务方法上添加事务注解 @Transactional -- 控制本地事务
Ⅶ、@GlobalTransactional -- 启动全局事务,只在主调用模块添加
在启动类上
四、Seata TCC
1、TCC 基本原理
TCC 与 Seata AT 事务一样都是两阶段事务,它与 AT 事务的主要区别为:
- TCC 对业务代码侵入严重
每个阶段的数据操作都要自己进行编码来实现,事务框架无法自动处理。 - TCC 效率更高
不必对数据加全局锁,允许多个事务同时操作数据。 - 有些业务AT完成不了,需要TCC
1、第一阶段 Try
当下订单时要扣减用户账户金额:
假如用户购买 100 元商品,要扣减 100 元。TCC 事务首先对这100元的扣减金额进行预留,或者说是先冻结这100元:
2、第二阶段 Confirm
如果第一阶段能够顺利完成,那么说明“扣减金额”业务(分支事务)最终肯定是可以成功的。当全局事务提交时, TC会控制当前分支事务进行提交,如果提交失败,TC 会反复尝试,直到提交成功为止。当全局事务提交时,就可以使用冻结的金额来最终实现业务数据操作:
3、第二阶段 Cancel
如果全局事务回滚,就把冻结的金额进行解冻,恢复到以前的状态,TC 会控制当前分支事务回滚,如果回滚失败,TC 会反复尝试,直到回滚完成为止。
4、多个事务并发的情况
多个TCC全局事务允许并发,它们执行扣减金额时,只需要冻结各自的金额即可:
2、TCC 事务模式,需要以下组件来支持全局事务的控制:
- TC 事务协调器
- TM 事务管理器
- RM 资源管理器
3、TCC项目中项目实战配置
分布式事务(七)Seata TCC模式-Spring Cloud微服务添加 TCC 分布式事务_wanght笔记-CSDN博客
①seata 依赖
②三个配置文件,与 AT 事务完全相同
application.yml -- 组名
registry.conf -- 注册中心地址
file.conf -- 组对应使用的协调器
③修改 Mapper,添加新的数据操作
④按照 seata 的规则,添加 TccAction 接口和实现,使用 Mapper 完成 TCC 数据库操作
import io.seata.rm.tcc.api.BusinessActionContext;
import io.seata.rm.tcc.api.BusinessActionContextParameter;
import io.seata.rm.tcc.api.LocalTCC;
import io.seata.rm.tcc.api.TwoPhaseBusinessAction;
import java.math.BigDecimal;/*
* 定义三个操作的方法是否执行成功
* T 冻结方法
* C 提交方法
* C 回滚方法
* */
@LocalTCC
public interface OrderTccAction {//该注解所在的方法是T(冻结数据)方法@TwoPhaseBusinessAction(name = "OrderTccAction" , // name:一般为接口名称commitMethod ="commit", //commitMethod:确认提交的方法名,默认commit可以省略rollbackMethod = "rollback") // rollbackMethod:表示回滚方法,默认rollback可以省略boolean prepare(BusinessActionContext ctx, //BusinessActionContext 上下文对象,在一二阶段之间传递数据@BusinessActionContextParameter(paramName = "orderId") Long orderId,//第二阶段使用第一阶段的orderId,通过注解放入上下文对象BusinessActionContext中Long userId,Long productId,Integer count,BigDecimal money);//为了避免seata的bug,将数据一个个单传,不能封装为对象。boolean commit(BusinessActionContext ctx);boolean rollback(BusinessActionContext ctx);
}
⑤修改业务方法,调用 TccAction 的第一阶段方法来冻结数据
⑥在第一个模块上添加 @GlobalTransactional 启动全局事务
4、遇到的问题
- 如果第一阶段冻结数据失败,仍然会执行二阶段的回滚操作
- 第二阶段失败,TC会重复下发二阶段执行指令,重复执行二阶段的数据操作
解决方法:幂等性控制,重复操作时,和一次操作结果相同
具体实施步骤
总体概述:
向事务中添加标记,标记为一个map集合的嵌套。
Map<Class<?>, Map<String, String>> //该分布式模块.class 事务id(在上下文对象中获取) 标记(自定义String类型作为标记)一阶段完成没有出错,添加一个标记,二阶段进行标记验证,如果没有标记,直接返回true结束程序,如果有标记,当二阶段执行完成时,删除标记,完美解决了前两个问题
步骤一:标记类的创建
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;//标记处理类
public class ResultHolder { //该分布式模块.class 事务id(在上下文对象中获取) 标记(自定义String类型作为标记)private static Map<Class<?>, Map<String, String>> map = new ConcurrentHashMap<Class<?>, Map<String, String>>();public static void setResult(Class<?> actionClass, String xid, String v) {Map<String, String> results = map.get(actionClass);if (results == null) {synchronized (map) {if (results == null) {results = new ConcurrentHashMap<>();map.put(actionClass, results);}}}results.put(xid, v);}public static String getResult(Class<?> actionClass, String xid) {Map<String, String> results = map.get(actionClass);if (results != null) {return results.get(xid);}return null;}public static void removeResult(Class<?> actionClass, String xid) {Map<String, String> results = map.get(actionClass);if (results != null) {results.remove(xid);}}
}
步骤二:在阶段一做标记的添加
步骤三:在第二阶段使用标记
seata分布式事务解决方案相关推荐
- 分布式事务解决方案Seata
一.Seata 简介 Seata 是 阿里巴巴2019年开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务.在 Seata 开源之前,Seata 对应的内部版本在阿里内 ...
- 关于seata分布式事务框架的几个问题
本文来说下关于seata分布式事务框架的几个问题 文章目录 概述 Seata 分布式事务解决方案比较 本文小结 概述 seata是两阶段提交事务,第一阶段解析业务sql并且生成对应快照,第二阶段是提交 ...
- seata 集群_【视频】 聊聊分布式事务解决方案seata
什么seata Seata 是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务.在 Seata 开源之前,Seata 对应的内部版本在阿里经济体内部一直扮演着分布 ...
- Spring Boot之基于Dubbo和Seata的分布式事务解决方案
转载自 Spring Boot之基于Dubbo和Seata的分布式事务解决方案 1. 分布式事务初探 一般来说,目前市面上的数据库都支持本地事务,也就是在你的应用程序中,在一个数据库连接下的操作,可以 ...
- 分布式事务解决方案,Seata的基本配置和使用
文章目录 1. 分布式事务介绍 ①:本地事务 ②:分布式事务 ③:常见的分布式事务解决方案 3. 2PC与3PC ①:2PC与3PC的区别 3. Seata介绍 ①:Seata的三种角色 ②:Seat ...
- 分布式事务解决方案 - SpringCloud Alibaba Seata
目录 github代码:GitHub - 18409489244/seata: 基于springcloud alibaba seata 的分布式事务demo 一.常见分布式事务解决方案 二.分布式事务 ...
- seata 分布式事务没有传递xid导致事务失效解决方案
seata 分布式事务没有传递xid导致事务失效解决方案 当spring cloud 设置全局开启分布式事务,在调用分支事务没有传递xid,原因是feign或者http调用时候 header 没有pu ...
- 微服务分布式事务解决方案Seata
文章目录 一.Seata是什么? 二.使用步骤 1.引入库 2.读入数据 总结 一.什么是Seata? Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用 的分布式事务服务.Sea ...
- Seata聚合 AT、TCC、SAGA 、 XA事务模式打造一站式的分布式事务解决方案
Seata Seata 是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务.在 Seata 开源之前,Seata 对应的内部版本在阿里经济体内部一直扮演着分布式一 ...
最新文章
- Android View之间的触摸事件传递图
- 使用Arquillian,Docker和Selenium使Web UI测试再次变得出色(第1部分)
- 广播 消息 没有服务器,服务器节点消息广播
- 非空验证方法(多值)和BindingResult提示验证信息
- jclasslib查看字节码
- PHP 5 将于年底停止更新,六成用户将面临安全风险
- 安捷伦频谱仪的使用方法图解_安捷伦N9020A频谱仪操作说明
- java messagedigest_Java MessageDigest.getInstance返回的实例非线程安全
- IE 11中 onpropertychange失效
- 华为悦盒6108V9-V9U-V9_PUB-6108V9C-非高安版-通刷精简固件及教程
- 涉密计算机怎么更新补丁,windows系统补丁你更新还是不更新?
- 第四百三十五章 灭龙魔宫
- ANTLR4(二) Vistor Listener
- 解决 Failed to fetch http://172.6.0.2/ubuntu/dists/jammy/main/binary-i386/Packages 404 Not Found问题
- DB2控制中心菜单中文乱码问题
- 用计算机在记事本做图案,记事本如何自定义制作CAD图案填充
- 如何构建自己的知识体系
- 美团后台开发秋招面经汇总(更新至2021-08-13)
- 如何编写Junit测试代码
- 数据分析项目实战项目一:CPC广告优化以及bilibili订单分析(下)