下载地址:Releases · seata/seata · GitHub

一、什么是分布式事务

首先这是普通事务:

下面是分布式事务:

在微服务系统中,每个微服务应用都可能会有自己的数据库,它们首先需要控制自己的本地事务。

一项业务操作可能会调用执行多个微服务。如何保证多个服务执行的多个数据库的操作整体成功或整体失败?这就是分布式事务要解决的问题。

二、Seata介绍

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

三、Seata AT

Seata 的 AT 模式(Automatic Transaction)是一种无侵入的分布式事务解决方案。

1、业务场景订单系统

当用户下订单时,执行以下三步流程:

  1. 订单系统保存订单
  2. 订单系统调用库存服务,减少商品库存
  3. 订单系统调用账户服务,扣减用户金额

这三步要作为一个整体事务进行管理,要么整体成功,要么整体失败。

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分布式事务解决方案相关推荐

  1. 分布式事务解决方案Seata

    一.Seata 简介 Seata 是 阿里巴巴2019年开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务.在 Seata 开源之前,Seata 对应的内部版本在阿里内 ...

  2. 关于seata分布式事务框架的几个问题

    本文来说下关于seata分布式事务框架的几个问题 文章目录 概述 Seata 分布式事务解决方案比较 本文小结 概述 seata是两阶段提交事务,第一阶段解析业务sql并且生成对应快照,第二阶段是提交 ...

  3. seata 集群_【视频】 聊聊分布式事务解决方案seata

    什么seata Seata 是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务.在 Seata 开源之前,Seata 对应的内部版本在阿里经济体内部一直扮演着分布 ...

  4. Spring Boot之基于Dubbo和Seata的分布式事务解决方案

    转载自 Spring Boot之基于Dubbo和Seata的分布式事务解决方案 1. 分布式事务初探 一般来说,目前市面上的数据库都支持本地事务,也就是在你的应用程序中,在一个数据库连接下的操作,可以 ...

  5. 分布式事务解决方案,Seata的基本配置和使用

    文章目录 1. 分布式事务介绍 ①:本地事务 ②:分布式事务 ③:常见的分布式事务解决方案 3. 2PC与3PC ①:2PC与3PC的区别 3. Seata介绍 ①:Seata的三种角色 ②:Seat ...

  6. 分布式事务解决方案 - SpringCloud Alibaba Seata

    目录 github代码:GitHub - 18409489244/seata: 基于springcloud alibaba seata 的分布式事务demo 一.常见分布式事务解决方案 二.分布式事务 ...

  7. seata 分布式事务没有传递xid导致事务失效解决方案

    seata 分布式事务没有传递xid导致事务失效解决方案 当spring cloud 设置全局开启分布式事务,在调用分支事务没有传递xid,原因是feign或者http调用时候 header 没有pu ...

  8. 微服务分布式事务解决方案Seata

    文章目录 一.Seata是什么? 二.使用步骤 1.引入库 2.读入数据 总结 一.什么是Seata? Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用 的分布式事务服务.Sea ...

  9. Seata聚合 AT、TCC、SAGA 、 XA事务模式打造一站式的分布式事务解决方案

    Seata Seata 是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务.在 Seata 开源之前,Seata 对应的内部版本在阿里经济体内部一直扮演着分布式一 ...

最新文章

  1. Android View之间的触摸事件传递图
  2. 使用Arquillian,Docker和Selenium使Web UI测试再次变得出色(第1部分)
  3. 广播 消息 没有服务器,服务器节点消息广播
  4. 非空验证方法(多值)和BindingResult提示验证信息
  5. jclasslib查看字节码
  6. PHP 5 将于年底停止更新,六成用户将面临安全风险
  7. 安捷伦频谱仪的使用方法图解_安捷伦N9020A频谱仪操作说明
  8. java messagedigest_Java MessageDigest.getInstance返回的实例非线程安全
  9. IE 11中 onpropertychange失效
  10. 华为悦盒6108V9-V9U-V9_PUB-6108V9C-非高安版-通刷精简固件及教程
  11. 涉密计算机怎么更新补丁,windows系统补丁你更新还是不更新?
  12. 第四百三十五章 灭龙魔宫
  13. ANTLR4(二) Vistor Listener
  14. 解决 Failed to fetch http://172.6.0.2/ubuntu/dists/jammy/main/binary-i386/Packages 404 Not Found问题
  15. DB2控制中心菜单中文乱码问题
  16. 用计算机在记事本做图案,记事本如何自定义制作CAD图案填充
  17. 如何构建自己的知识体系
  18. 美团后台开发秋招面经汇总(更新至2021-08-13)
  19. 如何编写Junit测试代码
  20. 数据分析项目实战项目一:CPC广告优化以及bilibili订单分析(下)

热门文章

  1. Hive对接Hbase
  2. Python金融数据分析可能用到的55个数据集,财富密码可能埋藏于此
  3. 揭秘手游外挂:基于内存蜜罐的内存修改挂分析技术
  4. 基于springboot+html汽车维修系统汽车维修系统的设计与实现
  5. 我的世界1.16.1java模组怎么加,我的世界1.16怎么加模组
  6. 练习-Java类和对象之对象引用之模拟手机功能
  7. 原生JS实现 购物车制作 和 楼梯导航(11)
  8. 香港智远:港股光伏板块中报期有望获资金青睐
  9. openpyxl常用用法
  10. SD卡烧录镜像后插电脑不显示问题