Seata分布式事务速览

警告
本文最后更新于 2024-03-09,文中内容可能已过时。

一、分布式事务基础 🔴

1、什么是分布式事务?

跨数据库、跨服务、跨模块的事务,要求:要么全部成功,要么全部回滚

单机事务:@Transactional 依靠数据库连接保证原子性。

分布式事务:多个服务、多个连接,本地事务失效,必须用分布式事务中间件。

2、分布式产生的问题

  • 服务A成功、服务B失败 → 数据不一致

  • 超时、网络抖动、重试导致重复提交

  • 最终数据错乱、资金对账不平、库存错乱

3、常见分布式事务方案 🔴

  1. 本地消息表(老旧):简单、低一致性、代码侵入大

  2. RabbitMQ可靠消息(最终一致性):适合异步、非强一致

  3. Seata(主流):微服务标准、支持四种模式

二、Seata 基础介绍

1、Seata 是什么

Seata 是阿里开源、微服务分布式事务标准框架,简单、高性能、无侵入,国内唯一主流。

2、三大核心角色 🔴

  1. TC 事务协调器:全局事务管理器、记录全局状态、通知提交/回滚(独立服务)

  2. TM 事务管理器:开启全局事务、向TC申请全局事务ID(业务服务)

  3. RM 资源管理器:管理本地事务、上报分支状态、执行undo/redo(业务服务)

3、全局事务流程(通用流程)

  1. TM 向 TC 申请开启全局事务,生成唯一 XID

  2. 各个微服务分支事务注册到 TC

  3. 业务执行完成,TM 判断全局结果

  4. 成功:TC 通知所有分支提交

  5. 失败:TC 通知所有分支回滚

三、Seata 四大事务模式 🔴

1、AT模式(最常用、生产95%使用)

1.1 特点

  • 无代码侵入,仅加注解 @GlobalTransactional

  • 基于数据库本地事务 + undo_log 快照

  • 二阶段提交、弱一致性、最终一致

  • 性能最好、最简单、互联网首选

1.2 AT底层原理 🔴

第一阶段:业务执行
  1. 执行业务SQL前,前置查询快照(before image)

  2. 执行业务增删改

  3. 执行后保存后置快照(after image)

  4. 快照存入 undo_log 表,本地事务提交

第二阶段:提交/回滚
  • 全局提交:异步删除undo_log,不阻塞业务

  • 全局回滚:读取undo_log快照,反向生成SQL回滚数据

1.3 at 行锁机制 🔴

AT 在一阶段提交了本地事务,没有数据库锁

全局行锁 + 隔离机制 防止脏写:

  • 同一行数据,未释放全局锁前,其他事务无法修改

  • 避免并发修改、数据错乱

1.4 AT模式三大经典问题 🔴

① 空回滚

分支没有执行SQL,却收到TC回滚指令。

解决:插入 undo_log空记录,标记已处理,防止二次回滚。

② 悬挂

一阶段业务执行太慢,二阶段先回滚完成,业务才执行SQL。

导致脏数据,永久无法回滚。

解决:事务拦截器判断XID,禁止滞后SQL执行

③ 脏写 🔴

两个事务同时修改一行,事务1回滚、事务2已提交,覆盖数据。

解决:全局锁+行级排他锁,锁住资源不让别人改。

2、TCC 模式(补偿事务)

2.1 三段式接口 🔴

  1. Try:资源检查、资源冻结、预留资源

  2. Confirm:确认执行业务、真正扣减

  3. Cancel:取消释放、资源回滚、补偿

2.2 优缺点

  • 优点:不依赖undo_log、无锁、高性能、适合高并发金融

  • 缺点:代码侵入极强、开发成本极高、要手写补偿逻辑

2.3 使用场景

金融、支付、资金、积分、高一致性场景。

3、XA 模式(强一致性)

  • 传统二阶段提交、数据库原生支持XA

  • 全程阻塞、锁时间长、性能差

  • 互联网几乎不用,银行传统行业用

4、SAGA 模式(长事务)

  • 长事务、流程复杂、耗时极长

  • 正向执行+反向补偿接口

  • 无锁、最终一致、允许中间数据不一致

四、四大模式超级对比表 🔴

模式 侵入性 一致性 性能 适用场景
AT 极低 最终一致 极高 普通微服务、电商、业务系统(95%)
TCC 极高 最终一致 支付、资金、金融、高并发
XA 强一致 传统银行、低并发
SAGA 最终一致 长流程、复杂业务、审批链

五、AT模式重点补充 🔴

1、undo_log表结构

保存:xid、分支id、前置快照、后置快照、sql类型、创建时间。

2、为什么AT性能高?

  • 一阶段本地事务直接提交,不阻塞业务

  • 二阶段提交异步删除快照

  • 只有回滚时才走反向SQL

3、AT隔离级别

默认 读未提交,存在中间数据可见问题。

解决方案:全局锁、悲观锁、业务加状态字段

六、Seata生产实战配置

1、核心依赖

1
2
3
4
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>

2、开启事务注解

1
2
3
4
5
// 全局事务(TM)
@GlobalTransactional(rollbackFor = Exception.class)
public void createOrder(){
    // 调用库存、支付、订单服务
}

3、yml配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
seata:
  application:
    name: seata-demo
  registry:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
  config:
    type: nacos
  tx-service-group: my_tx_group

七、生产常见坑+解决方案

  1. 超时事务未释放:TC定时清理、超时自动回滚、调大超时时间

  2. undo_log过大:定时清理、异步删除、限制大事务

  3. 全局锁竞争:热点数据拆分、减少长事务

  4. 重复提交:幂等性设计、唯一流水号

  5. 嵌套事务失效:禁止嵌套@GlobalTransactional

  6. 高并发脏写:业务加版本号乐观锁、减少并发修改同一行

八、总结 🔴

Seata是阿里开源微服务分布式事务框架,包含TC、TM、RM三大角色;

主流使用AT模式,一阶段执行业务保存undo_log快照并提交本地事务,二阶段决定异步删除或反向回滚;

AT存在空回滚、悬挂、脏写三大问题,分别通过空记录、拦截滞后SQL、全局锁解决;

另外还有TCC、XA、SAGA三种模式,TCC手写三段补偿接口适合金融,XA强一致性能差,SAGA适合长事务;

生产中AT无侵入、性能高,是互联网微服务首选,同时要注意事务超时、undo日志、幂等、脏写等生产问题。