Skip to content

SpringCloud_组件基本使用_Seata

1、什么是分布式事务

首先理解一下,为什么会用到分布式事务。

在分布式服务中,服务A中通过feign来调用服务B的方法,但是服务B的方法并不归属于服务A的事务体系中,因此如果此时服务B报错,并不会导致已经执行了的服务A的操作回退。

想要让服务A回退,那么就要让服务B纳入到服务A的事务体系中,也就是两者是同一个事务ID。这就是我们的分布式事务,它可以跨越服务来实现事务

想要实现分布式事务,我们有多种方式,可以通过像redis这样的中间件来实现。

但也可以用到我们今天介绍的seata组件来实现。甚至发展至今,一般我们谈到分布式事务,基本上seata已经成了我们的不二选择。

2、Seata 是什么

Seata 是一款分布式事务解决方案,为微服务架构提供了强一致性的分布式事务支持。提供了全局事务管理和本地事务协调的功能,可以用于确保多个微服务之间的事务操作的一致性;提供了 AT、TCC、SAGA和XA等几种事务模式。

常见的两种分布式事务模型:AT 模型(基于 TCC,Try-Confirm-Cancel)和 TCC 模型(基于两阶段提交)。

AT模型

默认使用的是 AT模式

  1. 在业务表所在的数据库中创建一个名为undo_log的表,用于记录回滚SQL,即与执行SQL相反的SQL(例如,执行insert则对应delete)。
  2. 当业务表执行操作时,Seata会解析执行的SQL,生成回滚SQL并存储到undo_log表中。
  3. 在本地事务提交前,向Seata服务端注册分支,申请业务表中对应数据行的全局锁,阻止其他事务对该数据进行更新操作。
  4. 本地事务提交时,业务数据的更新和生成的undo log一起提交。
  5. 将本地事务执行结果报告给Seata服务端,多个服务的本地事务使用相同的事务ID和分支ID记录在Seata服务端。
  6. 如果某个本地事务发生错误,Seata服务端发起对应分支的回滚请求。
  7. 同时开启本地事务,通过事务ID和分支ID查询undo_log表,执行回滚SQL,并将执行结果报告给Seata服务端。
  8. 如果没有错误发生,Seata服务端会在对应分支上发起请求,异步批量删除undo_log表中的记录。

总体来说,Seata服务端记录了所有本地事务,同时在每个库中记录了 undo log。

当发生错误时,通过事务ID和分支ID找到同一组的所有本地事务,利用记录的undo log统一回退数据。

3、使用 Seata 的基本步骤

seata分为服务端(TC)和客户端(TM,RM),

客户端通过引入jar包来使用。服务端需要我们单独安装。

  • TC(Transaction Coordinator):事务协调器,维护全局事务的运行状态,协调和落实全局事务的回滚提交
  • TM(Transaction Manager):控制全局事务的边界,负责开启一个全局事务,并最终发起全局事务提交或回滚的决议
  • RM(Resource Manager):控制分支(本地)事务,负责分支注册、状态汇报,并接受TC的指令,驱动本地事务的提交和回滚

1. 部署 Seata 服务器

服务端下载地址: https://github.com/seata/seata/releases

部署过程:略

2. seata客户端配置

在微服务的项目中,添加 Seata 的依赖。如果使用 Maven,可以在项目的 pom.xml 文件中添加以下依赖:

<dependency>
    <groupId>io.seata</groupId>
	    <artifactId>·-all</artifactId>
    <version>1.5.2</version> <!-- 请根据实际情况选择版本 -->
</dependency>

配置文件

在微服务的配置文件中,配置 Seata 客户端。通常需要指定 Seata 服务器的地址等信息。以下是一个示例配置:

seata:
  application-id: my-app
  tx-service-group: my-tx-group
  enabled: true
  config:
    type: nacos
    nacos:
      serverAddr: nacos-server:8848
      groupId: SEATA_GROUP
      namespace: ""
  registry:
    type: nacos
    nacos:
      serverAddr: nacos-server:8848
      groupId: SEATA_GROUP
      namespace: ""
  service:
    vgroup: "my-tx-group"
    group: "my-tx-group"

添加事务注解

使用 @GlobalTransactional 注解

在需要分布式事务的方法上,使用 @GlobalTransactional 注解标记。这个注解表示这个方法需要参与全局事务。

import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.stereotype.Service;

@Service
public class MyService {

    @GlobalTransactional(rollbackFor = Exception.class)
    public void businessMethod() {
        // 业务逻辑
    }
}

参考