目录

二、Seata 架构概述

三、Seata的生命周期

四、Seata Server(TC)环境搭建

五、四种事务模式详解

1. AT 模式(自动补偿)

2. XA 模式(强一致性)

3. TCC 模式(业务侵入)

3.1 常见开源TCC框架

3.2 原理

3.3 整体运行机制

3.4 关键问题处理

3.5 适用场景

3.6 缺点

3.7 与AT模式对比  

4. Saga 模式(长事务)


一、Seata 是什么?

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

Seata 官网Seata 是什么? | Apache Seata

Spring Cloud Alibaba Seata 官网概述-阿里云Spring Cloud Alibaba官网

Seata 官方 Demohttps://github.com/apache/incubator-seata-samples/ 

Seata AT/XA Demohttps://gitee.com/original-intention/seata-demo-gorgor

Seata Tcc Demohttps://gitee.com/original-intention/seata-tcc-demo-gorgor

二、Seata 架构概述

Seata 的核心组件分为三类角色:

  • TC (Transaction Coordinator):事务协调器(独立部署),维护全局和分支事务的状态,驱动全局事务提交或回滚。

  • TM (Transaction Manager):事务管理器(集成在业务服务),定义全局事务的范围:开始全局事务、提交或回滚全局事务(通过 @GlobalTransactional 注解触发)。

  • RM (Resource Manager):资源管理器(集成在业务服务),管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。

其中,TC 为单独部署的 Server 服务端,TM 和 RM 为嵌入到应用中的 Client 客户端。

三、Seata的生命周期

在 Seata 中,一个分布式事务的生命周期如下:
  1. TM 请求 TC 开启一个全局事务。TC 会生成一个 XID 作为该全局事务的编号。XID会在微服务的调用链路中传播,保证将多个微服务的子事务关联在一起。
  2. RM 请求 TC 将本地事务注册为全局事务的分支事务,通过全局事务的 XID 进行关联。
  3. TM 请求 TC 告诉 XID 对应的全局事务是进行提交还是回滚。
  4. TC 驱动 RM 们将 XID 对应的自己的本地事务进行提交还是回滚。

四、Seata Server(TC)环境搭建

Seata Server 2.0.0 下载地址:Seata Server 下载地址

Seata Server 参数配置:

  • Seata Server端存储模式(store.mode):现有file、db、redis、raft。
  • Seata 的注册中心:nacos, eureka, redis, zk, consul, etcd3, sofa
  • Seata 的配置中心:nacos, consul, apollo, zk, etcd3

本章使用的 Server端存储模式为 db,注册中心和配置中心为 nacos。

首先,先启动 nacos 服务。

接着,Seata 需修改的配置如下:

  • 步骤一:需要数据库执行 mysql.sql 脚本 

 表详情如下:

  • 步骤二:修改 application.yml 配置

 配置如下:

server:
  port: 7091

spring:
  application:
    name: seata-server

logging:
  config: classpath:logback-spring.xml
  file:
    path: ${log.home:${user.home}/logs/seata}

console:
  user:
    username: seata
    password: seata
seata:
  config:
    # support: nacos, consul, apollo, zk, etcd3
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      namespace: seata
      group: SEATA_GROUP
      context-path:
      username: nacos
      password: nacos
      data-id: seataServer.properties
  registry:
    # support: nacos, eureka, redis, zk, consul, etcd3, sofa
    type: nacos
    nacos:
      application: seata-server
      server-addr: 127.0.0.1:8848
      group: SEATA_GROUP
      namespace: seata
      cluster: default
      username:
      password:
  store:
    # support: file 、 db 、 redis 、 raft
    mode: file
  #  server:
  #    service-port: 8091 #If not configured, the default is '${server.port} + 1000'
  security:
    secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
    tokenValidityInMilliseconds: 1800000
    ignore:
      urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.jpeg,/**/*.ico,/api/v1/auth/login,/metadata/v1/**
  • 步骤三: application.yml 中,seataServer.properties 需要上传到 nacos 的配置文件中

配置如下

client.rm.asyncCommitBufferLimit=10000
client.rm.lock.retryInterval=10
client.rm.lock.retryPolicyBranchRollbackOnConflict=true
client.rm.lock.retryTimes=30
client.rm.reportRetryCount=5
client.rm.reportSuccessEnable=false
client.rm.sagaBranchRegisterEnable=false
client.rm.sagaJsonParser=fastjson
client.rm.sqlParserType=druid
client.rm.tableMetaCheckEnable=true
client.rm.tableMetaCheckerInterval=60000
client.rm.tccActionInterceptorOrder=-2147482648
client.tm.commitRetryCount=5
client.tm.defaultGlobalTransactionTimeout=60000
client.tm.degradeCheck=false
client.tm.degradeCheckAllowTimes=10
client.tm.degradeCheckPeriod=2000
client.tm.interceptorOrder=-2147482648
client.tm.rollbackRetryCount=5
client.undo.compress.enable=true
client.undo.compress.threshold=64k
client.undo.compress.type=zip
client.undo.dataValidation=true
client.undo.logSerialization=jackson
client.undo.logTable=undo_log
client.undo.onlyCareUpdateColumns=true
log.exceptionRate=100
metrics.enabled=false
metrics.exporterList=prometheus
metrics.exporterPrometheusPort=9898
metrics.registryType=compact
server.distributedLockExpireTime=10000
server.enableParallelRequestHandle=false
server.maxCommitRetryTimeout=-1
server.maxRollbackRetryTimeout=-1
server.recovery.asynCommittingRetryPeriod=1000
server.recovery.committingRetryPeriod=1000
server.recovery.rollbackingRetryPeriod=1000
server.recovery.timeoutRetryPeriod=1000
server.rollbackFailedUnlockEnable=false
server.session.branchAsyncQueueSize=5000
server.session.enableBranchAsyncRemove=false
server.undo.logDeletePeriod=86400000
server.undo.logSaveDays=7
server.xaerNotaRetryTimeout=60000
service.vgroupMapping.default_tx_group=default
store.db.branchTable=branch_table
store.db.datasource=druid
store.db.dbType=mysql
store.db.distributedLockTable=distributed_lock
store.db.driverClassName=com.mysql.cj.jdbc.Driver
store.db.globalTable=global_table
store.db.lockTable=lock_table
store.db.maxConn=30
store.db.maxWait=5000
store.db.minConn=5
store.db.password=root
store.db.queryLimit=100
store.db.url=jdbc:mysql://127.0.0.1:3306/seata_server_db?useUnicode=true&rewriteBatchedStatements=true
store.db.user=root
store.lock.mode=db
store.mode=db
store.publicKey=
store.session.mode=db
tcc.fence.cleanPeriod=1h
tcc.fence.logTableName=tcc_fence_log
transport.compressor=none
transport.enableRmClientBatchSendRequest=true
transport.enableTcServerBatchSendResponse=false
transport.enableTmClientBatchSendRequest=false
transport.heartbeat=true
transport.rpcRmRequestTimeout=30000
transport.rpcTcRequestTimeout=30000
transport.rpcTmRequestTimeout=30000
transport.serialization=seata
transport.server=NIO
transport.shutdown.wait=3
transport.threadFactory.bossThreadPrefix=NettyBoss
transport.threadFactory.bossThreadSize=1
transport.threadFactory.clientSelectorThreadPrefix=NettyClientSelector
transport.threadFactory.clientSelectorThreadSize=1
transport.threadFactory.clientWorkerThreadPrefix=NettyClientWorkerThread
transport.threadFactory.serverExecutorThreadPrefix=NettyServerBizHandler
transport.threadFactory.shareBossWorker=false
transport.threadFactory.workerThreadPrefix=NettyServerNIOWorker
transport.threadFactory.workerThreadSize=default
transport.type=TCP

 具体配置可以从Seata AT/XA Demo或 Seata Tcc Demo 案例项目中的 config 目录去找到。

  • 步骤四:点击 seata-server.bat 启动 Seata Server服务,这就是我们的TC服务。

五、四种事务模式详解

1. AT 模式(自动补偿)

  • 原理:基于两阶段提交(2PC)优化

    • 一阶段:解析业务 SQL,生成前后镜像(before_image/after_image)存入 undo_log,提交本地事务并释放本地锁。

    • 二阶段

      • 提交:异步删除 undo_log(快速完成)。

      • 回滚:对比当前数据与 after_image,若一致则用 before_image 回滚;若不一致(脏写)则转人工处理。

一阶段
业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。核心在于对业务sql进行解析,转换成undolog,并同时入库。
二阶段
  • 分布式事务操作成功,则TC通知RM异步删除undolog
  • 分布式事务操作失败,TM向TC发送回滚请求,RM 收到协调器TC发来的回滚请求,通过 XID 和 Branch ID 找到相应的回滚日志记录,通过回滚记录生成反向的更新 SQL 并执行,以完成分支的回滚。

  • 隔离性

    • 写隔离

      • 一阶段本地事务提交前,需要确保先拿到 全局锁 。
      • 拿不到 全局锁 ,不能提交本地事务。
      • 拿 全局锁 的尝试被限制在一定范围内,超出范围将放弃,并回滚本地事务,释放本地锁。
    • 读隔离

      • 在数据库本地事务隔离级别 读已提交(Read Committed) 或以上的基础上,Seata(AT 模式)的默认全局隔离级别是 读未提交(Read Uncommitted) 。需全局读已提交时使用 SELECT FOR UPDATE + @GlobalLock 代理申请全局锁。

  • 适用场景:纯数据库操作(如订单创建+库存扣减),对业务代码无侵入。

  • 缺点:存在脏读风险,高频更新场景全局锁竞争影响性能。

注意:

启动 Seata AT/XA Demo 项目时

  • 需要将项目中 /config/sql/all.sql 脚本在数据库中执行。

  • 需要将项目中 /config/nacos/seata-client.yml 脚本 上传到 nacos 中。

2. XA 模式(强一致性)

  • 原理:基于数据库原生 XA 协议的两阶段提交

    • 一阶段:执行 SQL 并注册分支到 TC,数据库锁定资源(不提交)。

    • 二阶段:TC 通知所有分支提交或回滚。

  • 整体运行机制

        XA 模式 运行在 Seata 定义的事务框架内:

  • 执行阶段(E xecute):

    • XA start/XA end/XA prepare + SQL + 注册分支
  • 完成阶段(F inish):

    • XA commit/XA rollback
  • 优点:强一致性,无脏读/脏写。

  • 缺点:资源锁定时间长,高并发下吞吐量低;依赖数据库 XA 支持(如 MySQL InnoDB)。

  • 适用场景:金融转账、传统数据库集成等强一致需求。

注意:

XA 模式与 AT 模式完全一致,如果要从AT模式切换成XA模式,只需要在Spring boot 启动类,加上以下配置,使用XA的数据源代理。

@EnableAutoDataSourceProxy(dataSourceProxyMode = "XA")

3. TCC 模式(业务侵入)

3.1 常见开源TCC框架
  • Seata TCC
  • Hmily
  • Tcc-Transaction
  • ByteTCC
  • EasyTransaction
3.2 原理

通过业务逻辑实现两阶段

  • Try:检查并预留资源(如冻结库存)。

  • Confirm:确认执行业务(如扣减冻结库存)。

  • Cancel:释放预留资源(如解冻库存)。

3.3 整体运行机制
  • 一阶段 prepare 行为
  • 二阶段 commit 或 rollback 行为

3.4 关键问题处理
  • 空回滚:Try 未执行时收到 Cancel,需记录标记避免误操作。

  • 防悬挂:Cancel 先于 Try 执行时,需拒绝后续 Try。

  • 幂等控制:通过事务 ID(XID)确保 Confirm/Cancel 只执行一次。

      具体解决流程如下:

        在 TCC 模型执行的过程中,还可能会出现各种异常,其中最为常见的有空回滚、幂等、悬挂等。TCC 模式是分布式事务中非常重要的事务模式,但是幂等、悬挂和空回滚一直是 TCC 模式需要考虑的问题,Seata 框架在 1.5.1 版本完美解决了这些问题。

如何处理空回滚

空回滚指的是在一个分布式事务中,在没有调用参与方的 Try 方法的情况下,TM 驱动二阶段回滚调用了参与方的 Cancel 方法。
那么空回滚是如何产生的呢?
如上图所示,全局事务开启后,参与者 A 分支注册完成之后会执行参与者一阶段 RPC 方法,如果此时参与者 A 所在的机器发生宕机,网络异常,都会造成 RPC 调用失败,即参与者 A 一阶段方法未成功执行,但是此时全局事务已经开启,Seata 必须要推进到终态,在全局事务回滚时会调用参与者 A 的 Cancel 方法,从而造成空回滚。
要想防止空回滚,那么必须在 Cancel 方法中识别这是一个空回滚,Seata 是如何做的呢?
Seata 的做法是新增一个 TCC 事务控制表,包含事务的 XID 和 BranchID 信息,在 Try 方法执行时插入一条记录,表示一阶段执行了,执行 Cancel 方法时读取这条记录,如果记录不存在,说明 Try 方法没有执行。

如何处理幂等

幂等问题指的是 TC 重复进行二阶段提交,因此 Confirm/Cancel 接口需要支持幂等处理,即不会产生资源重复提交或者重复释放。
那么幂等问题是如何产生的呢?
如上图所示,参与者 A 执行完二阶段之后,由于网络抖动或者宕机问题,会造成 TC 收不到参与者 A 执行二阶段的返回结果,TC 会重复发起调用,直到二阶段执行结果成功。
Seata 是如何处理幂等问题的呢?
同样的也是在 TCC 事务控制表中增加一个记录状态的字段 status,该字段有 3 个值,分别为:
  1. tried:1
  2. committed:2
  3. rollbacked:3
二阶段 Confirm/Cancel 方法执行后,将状态改为 committed 或 rollbacked 状态。当重复调用二阶段 Confirm/Cancel 方法时,判断事务状态即可解决幂等问题。

如何处理悬挂

悬挂指的是二阶段 Cancel 方法比 一阶段 Try 方法优先执行,由于允许空回滚的原因,在执行完二阶段 Cancel 方法之后直接空回滚返回成功,此时全局事务已结束,但是由于 Try 方法随后执行,这就会造成一阶段 Try 方法预留的资源永远无法提交和释放了。
那么悬挂是如何产生的呢?
如上图所示,在执行参与者 A 的一阶段 Try 方法时,出现网路拥堵,由于 Seata 全局事务有超时限制,执行 Try 方法超时后,TM 决议全局回滚,回滚完成后如果此时 RPC 请求才到达参与者 A,执行 Try 方法进行资源预留,从而造成悬挂。
Seata 是怎么处理悬挂的呢?
在 TCC 事务控制表记录状态的字段 status 中增加一个状态:
  • suspended:4
当执行二阶段 Cancel 方法时,如果发现 TCC 事务控制表没有相关记录,说明二阶段 Cancel 方法优先一阶段 Try 方法执行,因此插入一条 status=4 状态的记录,当一阶段 Try 方法后面执行时,判断 status=4 ,则说明有二阶段 Cancel 已执行,并返回 false 以阻止一阶段 Try 方法执行成功。

3.5 适用场景

资金交易、第三方服务集成(如支付接口)。

3.6 缺点

需手动编写三接口,开发成本高。

3.7 与AT模式对比  

AT 模式基于 支持本地 ACID 事务 的 关系型数据库

  • 一阶段 prepare 行为:在本地事务中,一并提交业务数据更新和相应回滚日志记录。
  • 二阶段 commit 行为:马上成功结束,自动 异步批量清理回滚日志。
  • 二阶段 rollback 行为:通过回滚日志,自动 生成补偿操作,完成数据回滚。

相应的,TCC 模式,不依赖于底层数据资源的事务支持:

  • 一阶段 prepare 行为:调用 自定义 的 prepare 逻辑。
  • 二阶段 commit 行为:调用 自定义 的 commit 逻辑。
  • 二阶段 rollback 行为:调用 自定义 的 rollback 逻辑。

所谓 TCC 模式,是指支持把 自定义 的分支事务纳入到全局事务的管理中。

4. Saga 模式(长事务)

概述

Saga 模式是 SEATA 提供的长事务解决方案,在 Saga 模式中,业务流程中每个参与者都提交本地事务,当出现某一个参与者失败则补偿前面已经成功的参与者,一阶段正向服务和二阶段补偿服务都由业务开发实现。

 适用场景:

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

优势:

  • 一阶段提交本地事务,无锁,高性能
  • 事件驱动架构,参与者可异步执行,高吞吐
  • 补偿服务易于实现

缺点:

  • 不保证隔离性
Logo

更多推荐