当前位置: 首页 > article >正文

分布式事务之Seata

概述

Seata有四种模式

AT模式:无侵入式的分布式事务解决方案,适合不希望对业务进行改造的场景,但由于需要添加全局事务锁,对影响高并发系统的性能。该模式主要关注多DB访问的数据一致性,也包括多服务下的多DB数据访问一致性问题。通过更新前快照回滚、更新后快照对比在二阶段提交时是否有人修改(为不受Seata代理的数据源做兜底),解决脏写。

优点:

  • 一阶段完成直接提交事务,释放数据库资源,性能比较好

  • 利用全局锁实现读写隔离

  • 没有代码侵入,框架自动完成回滚和提交

缺点:

  • 两阶段之间属于软状态,属于最终一致

  • 框架的快照功能会影响性能,但比XA模式要好很多

TCC模式:高性能的分布式事务解决方案,适用于对性能要求比较高的场景。该模式主要关注业务拆分,在按照业务横向扩展资源时,解决服务间调用的一致性问题。

优点:

  • 一阶段完成直接提交事务,释放数据库资源,性能好
  • 相比AT模型,无需生成快照,无需使用全局锁,性能最强
  • 不依赖数据库事务,而是依赖补偿操作,可以用于非事务型数据库
  • Redis这种也可以使用TCC模式

缺点:

  • 有代码侵入,需要人为编写try、Confirm和Cancel接口,太麻烦
  • 软状态,事务是最终一致
  • 需要考虑Confirm和Cancel的失败情况,做好幂等处理
  • 因为如果失败Seata会重试,所有要做好幂等

Saga模式:长事务的分布式事务解决方案,适用于业务流程长且需要保证事务最终一致性的业务系统。Saga 模式一阶段就会提交本地事务,无锁,长流程情况下可以保证性能,多用于渠道层、集成层业务系统,事务参与者可以是其它公司的服务也可以是遗留系统的服务,并且对于无法进行改造和提供 TCC 要求的接口,也可以使用 Saga 模式。

优点:

  • 一阶段提交本地数据库事务,无锁,高性能;

  • 参与者可以采用事务驱动异步执行,高吞吐;

  • 补偿服务即正向服务的“反向”,易于理解,易于实现;

缺点:

  • Saga 模式由于一阶段已经提交本地数据库事务,且没有进行“预留”动作,所以不能保证隔离性。后续会讲到对于缺乏隔离性的应对措施。

XA模式:强一致性。XA早期版本是一种规范 主流数据库对XA规范提供了支持,没有TM(事务管理者的概念)只有TC和RM。一阶段不提交事务,在第二阶段TM发起事务提交/回滚时才会让TC检查分支状态做提交/回滚因此是强一致性的

优点:

  • 强一致性
  • 易于使用:因为主流数据库都支持且无代码侵入

缺点:

  • 第一阶段不提交,在等待过程中占用数据库锁,占用系统资源,性能差

Seata核心组件

  • TC(Transaction Coordinator):全局事务协调器,负责管理全局事务的状态。
  • TM(Transaction Manager):事务管理器,负责发起全局事务,并向TC注册事务。
  • RM(Resource Manager):资源管理器,负责管理资源的本地事务,并向TC汇报事务状态。

前置条件

  1. 引入Seata依赖:在项目中引入Seata的依赖。
  2. 配置Seata服务:配置Seata的TC服务地址。
  3. 定义全局事务:使用@GlobalTransactional注解定义全局事务。

1. AT 模式(Auto Transaction)​

核心原理

  • ​两阶段提交:

  1. ​阶段一(Branch Commit)​:拦截业务 SQL,生成前置镜像(before image)和后置镜像(after image),保存到 UNDO_LOG 表。
    示例:执行 UPDATE product SET stock = stock - 10 WHERE id = 1 时,记录修改前的 stock=100 和修改后的 stock=90。
  2. 阶段二(Global Commit/Rollback)​:全局事务提交时,删除 UNDO_LOG;回滚时,根据镜像数据生成反向SQL(如 UPDATE product SET stock = 100 WHERE id = 1)。
  • ​全局锁机制:

在阶段一提交前,Seata 会获取记录的全局锁,防止其他事务修改同一数据,确保隔离性。

​应用场景

  • 单服务多数据源:

        例如订单服务同时操作 MySQL 和 PostgreSQL,需要保证两个库的事务一致性。

  • ​简单跨服务调用:

        服务 A 调用服务 B 的接口,两者均使用 AT 模式(如订单服务扣减库存服务)。

代码示例

// 订单服务(使用 AT 模式)
@GlobalTransactional // 开启全局事务
public void saveOrder(OrderRequest request) {// 1. 本地事务:创建订单orderDao.insert(request.getOrder());// 2. 远程调用库存服务(Feign 接口)storageFeign.discount(request.getProductId(), request.getCount());// 3. 模拟异常触发回滚if (request.getForceFail()) {throw new RuntimeException("Force rollback");}
}

关键细节

  • UNDO_LOG 表结构:需在业务库中提前创建,包含 branch_id、xid、rollback_info 等字段。
  • ​隔离性牺牲:AT 模式默认隔离级别为读未提交(Read Uncommitted),高并发场景可能脏读,需业务侧处理(如版本号校验)。
  • ​性能优化:避免单行数据频繁更新,防止全局锁竞争。

​2. TCC 模式(Try-Confirm-Cancel)​

核心原理

三阶段控制:

​Try:预留资源(如冻结库存、预扣余额),完成业务检查。
​Confirm:确认操作,真正执行业务(如扣减冻结的库存)。
​Cancel:回滚操作,释放预留资源(如解冻库存)。

业务侵入性:需手动编写 Try/Confirm/Cancel 接口,处理幂等性、空回滚、悬挂等问题。

​应用场景

  • ​资金交易:转账前预冻结账户金额,最终扣款或解冻。
  • ​第三方服务集成:调用外部 API(如支付接口)需要明确的成功/失败确认。

​代码示例

// TCC 接口定义(账户扣款)
public interface AccountTccService {@TwoPhaseBizAction(name = "deduct", commitMethod = "confirm", rollbackMethod = "cancel")boolean tryDiscount(@BizActionContextParameter(paramName = "userId") String userId,@BizActionContextParameter(paramName = "amount") BigDecimal amount);boolean confirm(BizActionContext context);boolean cancel(BizActionContext context);
}// Try 阶段实现(冻结资金)
@Override
public boolean tryDeduct(String userId, BigDecimal amount) {if (accountDao.getAvailableBalance(userId).compareTo(amount) < 0) {throw new RuntimeException("余额不足");}accountDao.freeze(userId, amount); // 冻结资金return true;
}// Confirm 阶段(实际扣款)
@Override
public boolean confirm(BizActionContext context) {String userId = (String) context.getActionContext("userId");BigDecimal amount = (BigDecimal) context.getActionContext("amount");accountDao.discount(userId, amount);  // 扣减冻结金额accountDao.unfreeze(userId, amount); // 解冻return true;
}// Cancel 阶段(解冻资金)
@Override
public boolean cancel(BizActionContext context) {String userId = (String) context.getActionContext("userId");BigDecimal amount = (BigDecimal) context.getActionContext("amount");accountDao.unfreeze(userId, amount);return true;
}

​关键细节

  • ​幂等性处理:
    通过唯一事务 ID(xid)确保 Confirm/Cancel 只执行一次。
  • ​空回滚问题:
    Try 未执行但收到 Cancel 请求时,需插入标记记录,避免误解冻。
  • ​悬挂问题:
    Cancel 比 Try 先到达时,需通过状态判断拒绝后续 Try 操作。

​3. Saga 模式

​核心原理

  • 事件驱动流程:
    将分布式事务拆分为多个本地事务,每个事务提交后触发下一个事务。若某个事务失败,按反向顺序执行补偿操作。
  • ​补偿机制:
    每个正向操作需定义对应的补偿方法(如 bookHotel() 对应 cancelHotel())。

​应用场景

  • ​长流程业务:
    旅行预订(机票 → 酒店 → 租车)、电商订单(下单 → 支付 → 发货)。
  • 渠道层、集成层业务:
    在渠道层和集成层业务中,往往需要与外部系统进行交互。例如,银行系统与第三方支付平台的集成,或者企业系统与ERP系统的集成。这些场景中,事务的跨服务特性使得Saga模式成为理想的解决方案。
  • ​跨公司服务集成:
    跨公司服务集成中,事务的分布式特性更加明显。例如,一个供应链系统可能涉及多个供应商、物流和零售商的协作。Saga模式通过补偿机制,可以有效地处理这些复杂场景中的事务问题。
  • 最终一致性场景:
    接受中间状态短暂不一致,但最终一致。Saga模式通过补偿操作保证最终一致性。如果某个Saga单元失败,系统会依次调用之前所有单元的补偿操作,回滚之前的操作。例如,如果支付服务扣款失败,系统会调用库存服务的补偿操作恢复库存。

​代码示例

//Saga 流程编排(状态机或注解驱动)
@SagaService
public class OrderSagaService {@Autowiredprivate InventoryService inventoryService;@Autowiredprivate PaymentService paymentService;@SagaStartpublic void createOrder(Order order) {// 1. 扣减库存inventoryService.discount(order.getProductId(), order.getQuantity());// 2. 发起支付paymentService.pay(order.getUserId(), order.getAmount());// 3. 更新订单状态为成功order.setStatus(OrderStatus.SUCCESS);orderDao.update(order);}@Compensatepublic void compensateOrder(Order order) {// 反向操作:释放库存、退款、订单状态回滚inventoryService.restore(order.getProductId(), order.getQuantity());paymentService.refund(order.getUserId(), order.getAmount());order.setStatus(OrderStatus.FAILED);orderDao.update(order);}
}

关键细节

  • ​状态机配置:
    可通过 JSON 或注解定义 Saga 流程,明确每个步骤的补偿方法。
  • ​超时管理:
    设置 Saga 事务超时时间,避免流程长期悬挂。
  • ​异步执行:
    适合结合消息队列(如 RocketMQ)实现异步 Saga。

​注:@Compensate

4. XA 模式

核心原理

  • ​传统两阶段提交:
    ​ Prepare 阶段:所有参与者(数据库)锁定资源,返回就绪状态。
     ​Commit/Rollback 阶段:协调者根据 Prepare 结果提交或回滚。
  • ​强一致性:
    所有资源在 Prepare 阶段锁定,直到全局事务结束。

​应用场景

  • ​金融核心系统:
    银行转账(必须保证双方账户同时成功或失败)。
  • ​传统数据库集成:
    旧系统迁移,依赖数据库原生 XA 协议。

​代码示例

// XA 数据源配置
@Bean
public DataSource dataSource() {MysqlXADataSource xaDataSource = new MysqlXADataSource();xaDataSource.setUrl("jdbc:mysql://localhost:3306/test");xaDataSource.setUser("root");xaDataSource.setPassword("***");return new AtomikosDataSourceBean(xaDataSource);
}// 业务方法(依赖 JTA)
@Transactional // 使用 JTA 事务管理器
public void transfer(String fromId, String toId, BigDecimal amount) {jdbcTemplate.update("UPDATE account SET balance = balance - ? WHERE id = ?", amount, fromId);jdbcTemplate.update("UPDATE account SET balance = balance + ? WHERE id = ?", amount, toId);
}

关键细节

  • ​性能瓶颈:
    全局锁持有时间长,高并发下吞吐量低。
  • ​数据库支持:
    需数据库支持 XA 协议(如 MySQL InnoDB、Oracle)。
  • ​调试复杂:
    XA 事务状态需通过数据库日志或 JTA 工具监控。

选型对比

​对比维度

维度ATTCC    SagaXA
​一致性弱隔离(读未提交)强隔离(预留资源)最终一致性强一致性
​性能高(短事务) 中(两阶段控制)高(异步流程)低(长锁)
​侵入性低(自动 UNDO_LOG)高(手动 TCC 接口)中(补偿方法)低(数据库支持)
适用场景 简单跨服务/多数据源 资金交易、第三方集成长流程业务金融核心、传统系统
​容错能力自动回滚需处理空回滚、悬挂需补偿逻辑完备依赖数据库 XA 恢复

决策树

  • 是否需要强一致性?
    是 → ​XA 模式​(金融场景)或 ​TCC 模式​(业务可控)。
    否 → 进入下一步。
  • ​是否为长流程业务?
    是 → ​Saga 模式​(如电商订单)。
    否 → 进入下一步。
  • ​是否希望低侵入?
    是 → ​AT 模式​(简单跨服务调用)。
    否 → ​TCC 模式​(精细化控制)。

​总结

  • AT 模式:快速解决 80% 的分布式事务问题,适合微服务新手。
  • ​TCC 模式:应对资金、库存等核心资源操作,牺牲开发效率换取高可靠性。
  • ​Saga 模式:长流程业务的终极方案,需接受最终一致性。
  • ​XA 模式:传统系统兼容选择,性能敏感场景慎用。

    实际开发中,多种模式在同一个工程中不可混用、不能同时使用,但可组合使用多种模式(如 AT + Saga),并配合消息队列、幂等设计、监控告警,构建健壮的分布式事务体系。

相关文章:

分布式事务之Seata

概述 Seata有四种模式 AT模式&#xff1a;无侵入式的分布式事务解决方案&#xff0c;适合不希望对业务进行改造的场景&#xff0c;但由于需要添加全局事务锁&#xff0c;对影响高并发系统的性能。该模式主要关注多DB访问的数据一致性&#xff0c;也包括多服务下的多DB数据访问…...

推测解码算法在 MTT GPU 的应用实践

前言​ 目前主流的大模型自回归解码每一步都只生成一个token, 尽管kv cache等技术可以提升解码的效率&#xff0c;但是单个样本的解码速度依然受限于访存瓶颈&#xff0c;即模型需要频繁从内存中读取和写入数据&#xff0c;此时GPU的利用率有限。为了解决这种问题&#xff0c;…...

Axure酒店管理系统原型

酒店管理系统通常被设计为包含多个模块或界面&#xff0c;以支持酒店运营的不同方面和参与者。其中&#xff0c;管理端和商户端是两个核心组成部分&#xff0c;它们各自承担着不同的职责和功能。 软件版本&#xff1a;Axure RP 9 预览地址&#xff1a;https://556i1e.axshare.…...

写实交互数字人在AI招聘中的应用方案

随着科技的进步&#xff0c;越来越多的行业开始探索如何利用人工智能提升效率和服务质量。其中&#xff0c;写实交互数字人技术以其高度拟真的交互体验和丰富的情感表达能力&#xff0c;在人力资源领域特别是招聘环节中展现出了巨大潜力。本文将探讨写实交互数字人在AI招聘中的…...

C++中IO类(iostream、fstream和sstream)知识详解和应用

一、C I/O 类体系概览 C 的 I/O 功能由一组 流&#xff08;stream&#xff09; 类封装&#xff0c;位于头文件 <iostream>、<fstream>、<sstream> 等。核心类别及其继承关系简图如下&#xff1a; ios_base↑basic_ios<CharT,Traits>↑┌───────…...

Spring Boot中如何对密码等敏感信息进行脱敏处理

以下是常见的脱敏方法及实现步骤&#xff0c;涵盖配置、日志和API响应等多个层面&#xff1a; ​1. 配置文件敏感信息脱敏​ (1) 使用加密库&#xff08;如Jasypt&#xff09; ​步骤​&#xff1a; 添加依赖&#xff1a; <dependency><groupId>com.github.ulise…...

React从基础入门到高级实战:React 基础入门 - JSX与组件基础

JSX 与组件基础 引言 在 React 开发中&#xff0c;JSX 和 组件 是两个最基础且核心的概念。JSX 是一种独特的语法&#xff0c;让你在 JavaScript 中编写类似 HTML 的代码&#xff0c;而组件则是 React 应用的基本构建块&#xff0c;帮助你将复杂的界面拆分为可复用的模块。本…...

房贷利率计算前端小程序

利率计算前端小程序 视图效果展示如下&#xff1a; 在这里插入代码片 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0&qu…...

在Visual Studio中进行cuda编程

首先下载与CUDA Toolkit匹配的Visual Studio版本 比如我的CUDA Toolkit版本是12.6&#xff0c;那么我可以使用2022的Visual Studio。 查看Toolkit版本 nvcc -V 配置 ok&#xff0c;让我们开始Visual Studio的nvcc编译器配置 参考例文https://github.com/apachecn/succinc…...

Fastrace:Rust 中分布式追踪的现代化方案

原文链接&#xff1a;Fastrace: A Modern Approach to Distributed Tracing in Rust | FastLabs / Blog 摘要 在微服务架构中&#xff0c;分布式追踪对于理解应用程序的行为至关重要。虽然 tokio-rs/tracing 在 Rust 中被广泛使用&#xff0c;但它存在一些显著的挑战&#xf…...

Linux云计算训练营笔记day13【CentOS 7 find、vim、vimdiff、ping、wget、curl、RPM、YUM】

Linux云计算训练营笔记day13[CentOS 7 find、vim、vimdiff、ping、wget、curl、RPM、YUM]] 目录 Linux云计算训练营笔记day13[CentOS 7 find、vim、vimdiff、ping、wget、curl、RPM、YUM]]1.find练习2.vim高级使用2.1 命令模式:2.2 插入模式:2.3 末行模式: 3. vimdiff4. ping5.…...

黑马Java基础笔记-15

Set 无索引&#xff0c;无序&#xff0c;不可重复 HashSet object类中默认hashCode的方法是根据地址值。 如果集合中存储的是自定义对象&#xff0c;必须要重写hashCode和equals方法。 底层原理 jdk8以前&#xff1a;数组 链表 jdk8及以后&#xff1a;数组 链表 红黑…...

Elasticsearch简单集成java框架方式。

Elasticsearch 在 Java 中最常用的客户端是什么&#xff1f;如何初始化一个 RestHighLevelClient&#xff1f;如何用 Spring Boot 快速集成 Elasticsearch&#xff1f;Spring Data Elasticsearch 如何定义实体类与索引的映射&#xff1f; 最常用的 Java 客户端 目前官方推荐使用…...

【RAG文档切割】从基础拆分到语义分块实战指南

目录 &#x1f31f; 前言&#x1f3d7;️ 技术背景与价值&#x1fa79; 当前技术痛点&#x1f6e0;️ 解决方案概述&#x1f465; 目标读者说明 &#x1f9e0; 一、技术原理剖析&#x1f4ca; 分块流程架构图&#x1f4a1; 核心分块策略&#x1f527; 关键技术模块 &#x1f6e…...

stream数据流

核心知识点&#xff1a;数据流&#xff08;Stream Data Flow&#xff09; 1. 通俗易懂的解释 想象一下你正在用花园里的水管浇花。水管里的水不是一次性全部倒出来的&#xff0c;而是持续不断地从水龙头流出&#xff0c;经过水管&#xff0c;最终从喷头喷洒到花上。在这个过程…...

利用 XML 外部实体注入(XXE)读取文件和探测内部网络

利用 XML 外部实体注入&#xff08;XXE&#xff09;读取文件和探测内部网络 引言 XML 外部实体注入&#xff08;XXE&#xff09;是一种常见的安全漏洞&#xff0c;攻击者可以通过这种漏洞读取服务器上的文件或探测内部网络。本文将通过一个实际的 Python 代码示例&#xff0c…...

软件设计师“排序算法”真题考点分析——求三连

一、考点分值占比与趋势分析 综合知识题分值统计表 年份考题数量总分值分值占比考察重点2018222.67%时间复杂度/稳定性判断2019334.00%算法特性对比分析2020222.67%空间复杂度要求2021111.33%算法稳定性判断2022334.00%综合特性应用2023222.67%时间复杂度计算2024222.67%分治…...

Visual Studio 2019/2022:当前不会命中断点,还没有为该文档加载任何符号。

1、打开调试的模块窗口&#xff0c;该窗口一定要在调试状态下才会显示。 vs2019打开调试的模块窗口 2、Visual Studio 2019提示未使用调试信息生成二进制文件 未使用调试信息生成二进制文件 3、然后到debug目录下看下确实未生成CoreCms.Net.Web.WebApi.pdb文件。 那下面的…...

vue--ofd/pdf预览实现

背景 实现预览ofd/pdf超链接功能 业务实现 pdf的预览 实现方式&#xff1a; 直接使用 <iframe :src"${url}#navpanes0&toolbar0" /> 实现pdf的预览。 navpanes0 隐藏侧边栏toolbar0 隐藏顶部工具栏 使用pdf.js&#xff0c;代码先行&#xff1a; <tem…...

Python 爬虫之requests 模块的应用

requests 是用 python 语言编写的一个开源的HTTP库&#xff0c;可以通过 requests 库编写 python 代码发送网络请求&#xff0c;其简单易用&#xff0c;是编写爬虫程序时必知必会的一个模块。 requests 模块的作用 发送网络请求&#xff0c;获取响应数据。 中文文档&#xf…...

【MySQL】CRUD

CRUD 简介 CRUD是对数据库中的记录进行基本的增删改查操作 Create&#xff08;创建&#xff09;Retrieve&#xff08;读取&#xff09;Update&#xff08;更新&#xff09;Delete&#xff08;删除&#xff09; 一、新增&#xff08;Create&#xff09; 语法&#xff1a; I…...

Spring Boot微服务架构(三):Spring Initializr创建CRM项目

使用Spring Initializr创建CRM项目 一、创建项目前的准备 访问Spring Initializr网站&#xff1a; 打开浏览器访问 https://start.spring.io/或者直接使用IDE&#xff08;如IntelliJ IDEA或Eclipse&#xff09;内置的Spring Initializr功能 项目基本信息配置&#xff1a; Proj…...

【笔记】PyCharm 中创建Poetry解释器

#工作记录 在使用 PyCharm 进行 Python 项目开发时&#xff0c;为项目配置合适的 Python 解释器至关重要。Poetry 作为一款强大的依赖管理和打包工具&#xff0c;能帮助我们更便捷地管理项目的依赖项与虚拟环境。下面将详细记录在 PyCharm 中创建 Poetry 解释器的步骤。 前提条…...

SDL2常用函数SDL事件处理:SDL_Event|SDL_PollEvent

SDL_Event SDL_Event是个联合体&#xff0c;是SDL中所有事件处理的核心。 SDL_Event是SDL中使用的所有事件结构的并集。 只要知道了那个事件类型对应SDL_Event结构的那个成员&#xff0c;使用它是一个简单的事情。 下表罗列了所有SDL_Event的所有成员和对应类型。 Uint32typ…...

RAID技术全解析:从基础到实战应用指南

一、RAID核心概念与级别对比 1. RAID的核心目标 数据冗余&#xff1a;通过镜像或校验机制防止数据丢失。 性能提升&#xff1a;利用条带化技术实现并行读写。 存储扩展&#xff1a;聚合多块磁盘容量&#xff0c;突破单盘限制。 2. 常见RAID级别对比 RAID级别最小磁盘数容…...

word通配符表

目录 一、word查找栏代码&通配符一览表二、word替换栏代码&通配符一览表三、参考文献 一、word查找栏代码&通配符一览表 序号清除使用通配符复选框勾选使用通配符复选框特殊字符代码特殊字符代码or通配符1任意单个字符^?一个任意字符?2任意数字^#任意数字&#…...

python中的numpy(数组)

&#xff08;0&#xff09;numpy介绍 NumPy是Python中用于科学计算的基础库&#xff0c;提供高效的多维数组对象ndarray&#xff0c;支持向量化运算&#xff0c;能大幅提高数值计算效率。它集成了大量数学函数&#xff08;如线性代数、傅里叶变换等&#xff09;&#xff0c;可…...

C++ 正则表达式简介

1. 正则表达式简介 正则表达式&#xff08;Regular Expression&#xff0c;简称Regex&#xff09;是一种用于匹配和处理文本的强大工具。它通过特定的符号组合形成匹配规则&#xff0c;常用于表单验证、文本搜索与替换、数据清洗等场景。 C11标准引入了 <regex> 头文件…...

iOS知识复习

block原理 OC block 是个结构体&#xff0c;内部有个一个结构体成员 专门保存 捕捉对象 Swift闭包 是个函数&#xff0c;捕获了全局上下文的常量或者变量 修改数组存储的内容&#xff0c;不需要加_block,修改数组对象本身时需要 weak原理 Weak 哈希表 &#xff08;散列表&a…...

rce命令执行原理及靶场实战(详细)

2. 原理 在根源上应用系统从设计上要给用户提供一个指定的远程命令操作的接口。漏洞主要出现在常见的路由器、防火墙、入侵检测等设备的web管理界面上。在管理界面提供了一个ping服务。提交后&#xff0c;系统对该IP进行ping&#xff0c;并且返回结果。如果后台服务器并没有对…...