侧边栏壁纸
  • 累计撰写 86 篇文章
  • 累计创建 94 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Seata 分布式事务教程与大厂高频面试题

温馨提示:
部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

基于 Apache Seata™ (incubating) 最新版本 2.6.0(2026-02-10 发布)编写,时间:2026年7月

目录

  1. Seata 概述
  2. 核心架构:TC/TM/RM 三大角色
  3. AT 模式详解(重点)
  4. TCC 模式详解
  5. SAGA 模式详解
  6. XA 模式详解
  7. 四种模式对比
  8. TC Server 部署与高可用
  9. Spring Cloud Alibaba 集成实战
  10. 生产环境最佳实践
  11. 大厂高频面试题(30道)

1. Seata 概述

1.1 什么是 Seata

Apache Seata™ (incubating) 是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能简单易用的分布式事务服务。Seata 的全称是 Simple Extensible Autonomous Transaction Architecture(简单可扩展自治事务架构)(Seata 官网)

它为用户提供了 AT、TCC、SAGA、XA 四种事务模式,打造一站式分布式事务解决方案,能够覆盖 99% 的业务场景 (阿里云开发者社区)

1.2 发展史

时间节点 关键事件
2019年1月 阿里开源 Fescar(Fast & Easy Commit and Rollback),定位分布式事务中间件
2019年4月 更名 Seata(Simple Extensible Autonomous Transaction Architecture)
2019年12月 Seata GA 版本(1.0.0)发布,AT 模式生产可用
2023年10月 Seata 进入 Apache 孵化器,更名为 Apache Seata (incubating),Maven groupId 从 io.seata 变为 org.apache.seata (CSDN 实战)
2023年11月 2.0.0 发布,是 ASF 孵化前的过渡版本,优化 TCC 结构、支持 API 访问 (Seata 官网)
2024年9月 2.1.0 发布,Saga 解耦 Spring、支持 RocketMQ 事务、支持 Raft 节点元数据同步
2024年10月 2.2.0 发布(首个 ASF 发布版本)
2025年8月 2.5.0 发布,修复 Fury 反序列化漏洞、优化 Raft 模式事务大小检查、增强 HTTP/2 协议支持 (CSDN 生产实战)
2026年2月 2.6.0 最新版发布:新增 Console 端 MCP Server 支持、优化 Netty 协议并简化配置、修复 YAML 兼容性、实现多数据源下同源分支事务的合并、移除 Saga 模式的 @LocalTCC 注解 (Seata 下载页)

1.3 最新版本核心特性(2.6.0)

  • Console MCP Server 支持:Seata 控制台支持 MCP 协议,便于 AI Agent 集成
  • Netty 协议优化:简化配置,提升通信性能
  • 多数据源同源分支事务合并:同一数据源下的多个分支事务可合并,减少全局锁竞争
  • Saga 模式架构优化:移除 @LocalTCC 注解,解耦 Spring 依赖
  • Raft 集群模式成熟:从 2.1.0 起支持原生 Raft 共识,2.5.0+ 已优化事务大小检查,生产可用
  • TCC Fence 篱笆机制(1.5.1+引入):框架层面解决 TCC 空回滚/悬挂/幂等三大问题 (CSDN TCC Fence)

1.4 生态定位

Seata 已在阿里、美团、滴滴、京东等大厂大规模生产部署,支撑过双11核心交易链路,是国内微服务架构下分布式事务的事实标准。它完美适配 Spring Cloud、Spring Cloud Alibaba、Dubbo、Motan、gRPC 等主流 RPC 框架,支持 MySQL、PostgreSQL、Oracle、达梦、PolarDB-X 等多种数据库 (Seata 官网)

2. 核心架构:TC/TM/RM 三大角色

Seata 的分布式事务由三大核心组件协同完成:

2.1 三大角色

角色 全称 部署位置 核心职责
TC Transaction Coordinator(事务协调者) 独立部署的 Seata Server 集群 维护全局/分支事务状态;生成全局唯一 XID;驱动全局提交或回滚;管理全局锁分配与释放 (阿里云开发者社区)
TM Transaction Manager(事务管理器) 嵌入业务发起方应用 定义全局事务边界;向 TC 申请开启/提交/回滚全局事务;将 XID 沿调用链路传播 (CSDN 实战)
RM Resource Manager(资源管理器) 嵌入每个参与服务的应用 管理分支事务资源;向 TC 注册分支并上报状态;接收 TC 指令驱动分支提交/回滚;AT 模式下负责生成 undo_log (51CTO)

2.2 整体事务流程

image.png

关键概念

  • XID(Global Transaction ID):全局事务唯一标识,在整个分布式调用链路中传播,是关联所有分支事务的纽带
  • Branch ID:每个分支事务在全局事务中的唯一标识
  • 事务分组(TxServiceGroup):逻辑分组,通过 vgroupMapping 映射到实际的 TC 集群名,实现多集群隔离 (CSDN Nacos 部署)

3. AT 模式详解(重点)

AT 模式是 Seata 默认的事务模式,也是面试最高频考点。它是无侵入的两阶段提交改进方案——业务代码几乎零改造,一个 @GlobalTransactional 注解即可开启全局事务。

3.1 前提条件

  1. 基于支持本地 ACID 事务的关系型数据库(MySQL、PostgreSQL、Oracle 等)
  2. Java 应用,通过 JDBC 访问数据库
  3. 必须在每个参与事务的数据库创建 undo_log (阿里云开发者社区)

3.2 一阶段流程(核心)

AT 模式的核心创新是:一阶段就直接提交本地事务,不像传统 2PC 那样锁住资源等待

Seata 通过代理 DataSource,拦截所有业务 SQL,在执行前后自动完成以下操作:

  1. 解析 SQL:识别 SQL 类型(INSERT/UPDATE/DELETE)、表名、条件、参数
  2. 查询前镜像(Before Image):根据 SQL 条件查询修改前的数据快照
  3. 执行业务 SQL:执行业务原始 SQL
  4. 查询后镜像(After Image):查询修改后的数据快照
  5. 生成回滚日志:将前后镜像、SQL 元信息组织成回滚日志,写入 undo_log
  6. 提交本地事务:业务数据更新 + undo_log 在同一个本地事务中提交,释放本地锁和连接资源
  7. 向 TC 注册分支并申请全局锁:提交前先获取全局锁,防止脏写 (51CTO)

以扣库存为例:

-- 业务 SQL
UPDATE stock SET count = count - 10 WHERE commodity_code = 'C001';

-- Seata 自动执行:
-- 1. 前镜像
SELECT count FROM stock WHERE commodity_code = 'C001';  -- before: count=100
-- 2. 执行业务 SQL
UPDATE stock SET count = count - 10 WHERE commodity_code = 'C001';
-- 3. 后镜像
SELECT count FROM stock WHERE commodity_code = 'C001';  -- after: count=90
-- 4. 写入 undo_log
INSERT INTO undo_log (branch_id, xid, rollback_info)
VALUES (1, 'xxx', '{"beforeImage":{"count":100},"afterImage":{"count":90},"sqlType":"UPDATE"}');
-- 5. 提交本地事务,申请全局锁
COMMIT;

(51CTO)

3.3 二阶段流程

3.3.1 二阶段提交(全局成功)

因为一阶段已经提交了本地事务,二阶段提交只需做清理工作

  • TC 通知各 RM 异步删除 undo_log 记录
  • 释放全局锁
  • 这个过程非常快速,不阻塞业务 (CSDN Spring Cloud)

3.3.2 二阶段回滚(全局失败)

  • TC 通知各 RM 执行回滚
  • RM 查找 undo_log 记录,取出 before image
  • 对比 after image 与当前数据库数据(脏写校验),若数据被非 Seata 事务修改过则告警、人工介入
  • 根据 before image 生成反向 SQL 并执行,恢复数据
  • 删除 undo_log,释放全局锁 (阿里云开发者社区)

反向 SQL 生成规则:

  • INSERT 回滚 → DELETE
  • DELETE 回滚 → INSERT(用 before image)
  • UPDATE 回滚 → SET 回 before image 值

3.4 undo_log 表结构

每个业务库必须创建 undo_log 表:

CREATE TABLE IF NOT EXISTS `undo_log` (
  `branch_id`     BIGINT       NOT NULL COMMENT '分支事务ID',
  `xid`           VARCHAR(128) NOT NULL COMMENT '全局事务ID',
  `context`       VARCHAR(128) NOT NULL COMMENT '上下文(序列化方式等)',
  `rollback_info` LONGBLOB     NOT NULL COMMENT '回滚信息(before/after image)',
  `log_status`    INT          NOT NULL COMMENT '状态(0=正常,1=已删除)',
  `log_created`   DATETIME     NOT NULL COMMENT '创建时间',
  `log_modified`  DATETIME     NOT NULL COMMENT '修改时间',
  PRIMARY KEY (`branch_id`),
  UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;

(CSDN 面试题)

3.5 全局锁与写隔离

全局锁是 Seata AT 模式实现隔离性的核心机制。它由 TC 统一管理,锁的粒度是表名 + 主键值(行级锁)。

写隔离流程

事务A(全局事务):
  ① 一阶段本地事务提交前,先向 TC 申请获取该行的全局锁
  ② 获取全局锁成功后,提交本地事务(仍持有全局锁)
  ③ 二阶段提交/回滚完成后,释放全局锁

事务B(全局事务):
  ① 修改同一行数据,尝试获取全局锁
  ② 全局锁被事务A持有 → 重试等待(自旋,不是阻塞)
  ③ 默认重试 30 次,每次间隔 10ms,超时则失败回滚
  ④ 事务A释放锁后,事务B获取全局锁继续执行

(CSDN 架构解析)

关键点

  • 全局锁在一阶段本地事务提交前获取,在二阶段结束后释放
  • 本地锁在一阶段提交后立即释放——所以数据库行锁持有时间极短,不会长时间占用数据库连接
  • 全局锁由 TC 集中管理,确保所有 Seata 管理的全局事务之间不会发生脏写
  • 但如果非 Seata 控制的事务(比如直接通过数据库客户端修改)修改了同一行,Seata 无法感知,这是 AT 模式的局限 (51CTO)

3.6 读隔离

AT 模式的默认隔离级别是读未提交(Read Uncommitted),因为一阶段已经提交本地事务,其他本地事务可以读到这个尚未全局提交的数据(中间状态)。

如果业务需要读已提交隔离级别,Seata 提供两种方案:

  1. SELECT ... FOR UPDATE 语句代理:Seata 对 FOR UPDATE 的查询语句会申请全局锁,如果全局锁被其他事务持有,则释放本地锁重试,直到全局锁被释放,保证读到的一定是已全局提交的数据。但这会降低并发性能。
  2. 全局读锁(Seata 1.4+):通过 @GlobalLock 注解或配置 client.rm.lock.retryInterval/policyBranch 实现更细粒度的读隔离控制 (CSDN 架构解析)

面试口诀:AT 默认读未提交,因为一阶段提交本地事务了;要读已提交用 SELECT FOR UPDATE,但性能会降级。

3.7 脏写校验

二阶段回滚时,Seata 会将 after image 与数据库当前数据做对比。如果当前数据已经被非 Seata 控制的操作修改(即 after image 与当前数据不一致),说明发生了脏写。此时 Seata 不会自动回滚,而是打印错误日志、输出告警,转人工处理——因为框架无法判断如何正确回滚 (CSDN 实战)

3.8 AT 模式的性能瓶颈

AT 模式在高并发场景下存在两个核心瓶颈 (美团三面文章)

  1. 全局锁竞争:每一个写操作都要去 TC 拿全局锁,在 QPS 5万+ 的秒杀场景下,全局锁排队超过5秒可能导致全链路超时
  2. undo_log IO 开销:每个写操作都要查询前后镜像 + 写 undo_log,数据库 IOPS 开销比 TCC 高 47%
  3. 脏写风险:非 Seata 事务绕过框架修改数据会导致 undo_log 失效

优化手段

  • 热点数据库存分桶:将一个 SKU 的库存分散到多条记录,降低锁竞争 (掘金)
  • 混合模式:热点扣减用 TCC,非热点用 AT
  • 调优锁重试参数:client.rm.lock.retry-interval=10retry-times=30

4. TCC 模式详解

TCC(Try-Confirm-Cancel)是业务层面的两阶段提交方案,不依赖数据库事务,完全由业务代码控制资源预留和确认/释放。

4.1 三阶段模型

阶段 名称 职责 类比
Try 资源预留 检查业务合法性,预留必要资源(冻结库存、冻结余额) 占座
Confirm 确认执行 所有分支 Try 成功后执行,真正使用预留资源完成业务操作(扣减冻结库存) 付款出票
Cancel 取消回滚 任一 Try 失败或超时,释放 Try 阶段预留的资源(解冻库存、解冻余额) 取消释放座位

(阿里云开发者社区)

以账户扣减为例:

  • Try:检查余额是否充足,将部分金额从"可用余额"转移到"冻结余额"
  • Confirm:将"冻结余额"直接扣减(不再动可用余额)
  • Cancel:将"冻结余额"恢复回"可用余额"

4.2 与 AT 模式的核心区别

维度 AT TCC
实现层次 数据源代理层,自动生成反向 SQL 业务代码层,手动编写三阶段方法
侵入性 零侵入,一个注解即可 高侵入,每个接口拆分为 Try/Confirm/Cancel 三个方法
全局锁 需要,由 TC 管理 不需要,应用层通过资源预留实现隔离
undo_log 需要 不需要
依赖数据库 必须是关系型数据库 不依赖,可操作 Redis、MongoDB、第三方 API (CSDN 对比)
性能 中(有全局锁和 undo_log IO) 最高(无全局锁,一阶段即完成数据写入)
适用场景 常规业务、管理后台 高并发核心链路(支付、秒杀、资金)

性能数据(100线程并发压测):TCC 平均响应时间 92ms vs AT 的 185ms,TPS 1085 vs 540,秒杀场景下 TCC 吞吐量可达 AT 的 12 倍 (CSDN 架构解析)

4.3 TCC 接口定义(Seata 2.x)

@TwoPhaseBusinessAction(
    name = "storageTccService",           // TCC 接口全局唯一名称
    commitMethod = "confirm",             // 二阶段确认方法名
    rollbackMethod = "cancel",            // 二阶段回滚方法名
    useTCCFence = true                    // 开启 TCC Fence 防护(生产必开)
)
public boolean tryFreezeStorage(
    BusinessActionContext context,
    @BusinessActionContextParameter(paramName = "productId") Long productId,
    @BusinessActionContextParameter(paramName = "count") Integer count);

public boolean confirm(BusinessActionContext context);
public boolean cancel(BusinessActionContext context);

(CSDN 实战)

4.4 三大经典异常与解决方案(面试超高频)

TCC 模式在网络不可靠环境下会遇到空回滚、悬挂、幂等三大问题,Seata 1.5.1+ 通过 TCC Fence(TCC 篱笆)机制,用一张 tcc_fence_log 表在框架层面统一解决 (CSDN TCC Fence)

4.4.1 空回滚(Empty Rollback)

场景:Try 请求由于网络丢包/拥堵,根本没到达 RM;但 TM 因超时决定回滚,TC 向 RM 下发了 Cancel 请求。Cancel 直接执行"释放资源"会导致凭空多出资源(资损)。

防御:Cancel 执行前查询 tcc_fence_log 表,如果没有对应 Try 记录,说明 Try 未执行,直接返回成功(什么都不做),同时插入一条 SUSPENDED 状态记录防止悬挂。

4.4.2 悬挂(Suspension)

场景:空回滚的"孪生兄弟"。Cancel 先执行完了(空回滚),被延迟的 Try 请求才到达 RM 并成功执行(冻结了资源)。但此时全局事务已结束,不会再有 Confirm/Cancel 来处理这笔资源,导致资源永久悬挂泄漏

防御:Cancel 空回滚时插入 SUSPENDED 标记;迟到的 Try 执行前查表,发现 SUSPENDED 记录后直接拒绝执行,抛出异常。

4.4.3 幂等性(Idempotency)

场景:网络抖动导致 TC 未收到 RM 的 Confirm/Cancel 响应,TC 会重试下发指令。Confirm/Cancel 被重复执行会导致数据重复扣减/释放。

防御:通过 tcc_fence_log 状态机控制——Confirm/Cancel 执行前检查状态,如果已经是 COMMITTED/ROLLBACKED,直接返回成功;否则执行业务逻辑并更新状态 (CSDN TCC 防御)

4.4.4 tcc_fence_log 状态机

                     Try 执行成功
  [不存在] ──────────────────────────────→ [TRIED]
     │                                        │
     │ Cancel先到(空回滚)                    │ Confirm成功
     ↓                                        ↓
[SUSPENDED]                              [COMMITTED]
     ↑                                        │
     │ Try迟到时拒绝                           │ Cancel成功
     │                                        ↓
     └────────── 拒绝Try执行              [ROLLBACKED]

开启方式:在 @TwoPhaseBusinessAction 注解中设置 useTCCFence = true,并在业务库创建 tcc_fence_log 表即可,框架自动处理 (CSDN TCC Fence)

4.5 TCC 适用场景

  • 高并发核心交易链路:支付、转账、秒杀库存扣减
  • 资源预留类业务:账户余额冻结、优惠券锁定、额度预占
  • 跨异构资源场景:操作 Redis、MQ、第三方 API 等非关系型资源 (美团三面文章)

5. SAGA 模式详解

SAGA 模式是 Seata 提供的长事务解决方案,适用于业务流程长、参与服务多的场景。

5.1 核心思想

SAGA 模式将一个长事务拆分为一系列本地短事务,每个本地事务都有对应的补偿事务。如果某个本地事务失败,按相反顺序执行前面已成功事务的补偿操作,最终达到数据一致性 (阿里云开发者社区)

5.2 两种实现方式

实现方式 说明
状态机引擎(推荐) 通过 JSON 状态图定义服务调用流程和补偿关系,由 Seata 状态机引擎驱动执行。支持可视化设计器(Seata Console 集成 Saga StateMachine Designer),支持单项选择、并发、子流程、参数转换、异常捕获 (Seata 2.1 Release Notes)
注解方式 使用 @SagaStart@Compensable 注解标记正向和补偿方法,实现简单但灵活性较低 (CSDN Spring Cloud)

5.3 状态机执行流程

正向执行:[StateA] → [StateB] → [StateC] → [StateD 失败!]
补偿执行:                         ↓
         [StateA补偿] ← [StateB补偿] ← [StateC补偿](反向补偿已成功的步骤)

特点

  • 一阶段直接提交本地事务,无全局锁,无长事务
  • 二阶段补偿通过编写反向操作实现
  • 无隔离性:正向执行过程中,其他事务可以看到中间状态,存在脏写风险
  • 补偿逻辑可能失败,需要人工干预兜底 (CSDN 对比)

5.4 SAGA 适用场景

  • 长事务/跨多服务业务流:订单履约(创建订单→扣库存→扣款→物流创建→通知)
  • 需要服务编排:复杂业务流程编排(支持条件判断、子流程、并发分支)
  • 允许最终一致性:对中间状态短暂不一致可接受的场景
  • 2.6.0 重要变更:移除了 Saga 模式的 @LocalTCC 注解,Saga 完全解耦 Spring (Seata 下载页)

5.5 SAGA vs TCC

维度 SAGA TCC
事务长度 长事务(分钟级甚至小时级) 短事务(秒级)
隔离性 无隔离,有脏写风险 通过资源预留实现隔离
开发成本 中等(编写正向+补偿) 高(编写三个方法)
性能 极高(异步无锁) 高(无全局锁)
补偿方向 反向补偿链 单个 Cancel

6. XA 模式详解

XA 模式基于数据库原生的 XA 协议实现强一致性的两阶段提交,Seata 作为事务协调器驱动整个流程。

6.1 核心机制

XA 协议是 X/Open 组织提出的分布式事务标准,MySQL、Oracle、PostgreSQL 等主流数据库都原生支持。

执行阶段(Phase 1 - Prepare)

  1. RM 开启 XA 分支,执行业务 SQL
  2. 执行 XA PREPARE:将事务持久化到数据库(之后任何意外都不会丢失),但不提交
  3. 此时持有数据库锁和连接,等待 TC 指令
  4. RM 向 TC 报告准备状态 (阿里云开发者社区)

完成阶段(Phase 2 - Commit/Rollback)

  • 所有分支 Prepare 成功 → TC 通知所有 RM 执行 XA COMMIT
  • 任一分支失败 → TC 通知所有 RM 执行 XA ROLLBACK

6.2 XA vs AT

维度 XA AT
一致性 强一致性(ACID) 最终一致性(接近强一致)
锁持有时间 全程持有数据库锁和连接,直到二阶段结束 一阶段提交后释放本地锁,仅持全局锁至二阶段
性能 (长事务阻塞数据库连接) 高(接近本地事务性能)
侵入性 无(仅配置) 低(需建 undo_log 表)
数据库要求 必须支持 XA 协议 支持本地 ACID 的关系型数据库
undo_log 不需要 需要
适用场景 金融核心强一致、低并发 通用业务、高并发 (CSDN 对比)

6.3 XA 模式的致命缺陷

  1. 长事务阻塞:一阶段 Prepare 后到二阶段结束前,一直持有数据库行锁和连接
  2. 并发能力极低:在高并发场景下数据库连接池会被耗尽
  3. 协调者单点风险:TC 在 Prepare 后宕机,各分支会一直持有锁,需数据库管理员手动 XA RECOVER 处理

结论:XA 模式实际生产中极少使用,仅在对一致性要求极高且并发量极低的特殊场景(如银行核心转账批处理)才考虑 (CSDN 架构解析)

7. 四种模式对比

7.1 核心对比表

对比维度 AT 模式 TCC 模式 SAGA 模式 XA 模式
一致性 最终一致(接近强一致) 最终一致 最终一致 强一致
侵入性 无(仅注解) (三个方法) 中(正向+补偿) 无(仅配置)
性能 中(有全局锁) (无全局锁) 极高(异步无锁) 低(阻塞)
并发能力
隔离性 全局锁(默认读未提交) 业务层资源预留 无隔离 读已提交
锁持有 全局锁短时间持有 业务层预留(无锁) 无锁 全程持DB锁
依赖 关系型数据库 不依赖(任意资源) 不依赖 支持 XA 的数据库
事务长度 短事务 短事务 长事务 短事务
开发成本 极低 极高
异常处理 自动(undo_log) Fence 机制/手动 手动补偿 自动
典型场景 通用业务、管理后台 支付/秒杀/资金核心 订单履约/长流程/服务编排 金融批处理、强一致

(阿里云开发者社区) (CSDN 对比) (CSDN Spring Cloud)

7.2 选型决策树

业务需求是什么?
│
├─ 需要强一致且并发不高?→ XA 模式
│
├─ 业务流程长(跨多服务/耗时久)?→ SAGA 模式
│
├─ 高并发核心链路(支付/秒杀)?
│   ├─ 团队 TCC 开发成本可接受?→ TCC 模式
│   └─ 追求开发效率?→ AT + 热点优化(分桶/混合模式)
│
└─ 常规业务/内部系统/追求快速落地?→ AT 模式(默认首选)

大厂选型原则(美团/阿里标准)(美团三面文章)

  • 强一致短事务(支付/下单/扣库存)→ TCC
  • 最终一致长事务(订单履约/物流)→ SAGA/本地消息表
  • 低并发简单跨库(管理后台/配置系统)→ AT
  • 原则:能用最终一致就不用强一致,Seata 的全局锁和网络开销会降低吞吐量

8. TC Server 部署与高可用

8.1 存储模式对比

TC 存储全局事务、分支事务、全局锁等会话数据,支持四种存储模式:

存储模式 一致性 性能 高可用 适用场景
file 强一致(本地文件) ❌ 不支持,单节点 本地开发测试
db 强一致(依赖DB事务) ✅ 支持(共享DB) 生产主流方案 (腾讯云)
redis 最终一致(Redis异步落盘) ✅ 支持(Redis集群) 高并发、允许少量数据丢失
raft 强一致(Raft共识) ✅ 支持(3+节点内嵌Raft) 2.6.0 推荐生产方案,无需外置DB (CSDN 生产)

注意:生产环境严禁使用 file 模式。推荐 Raft 模式(2.1.0+,2.6.0成熟稳定)或 DB模式(MySQL 主从)。

8.2 DB 模式核心表

使用 DB 存储模式需要创建 Seata Server 专用的数据库表:

表名 作用
global_table 存储全局事务元数据(XID、状态、超时时间等)
branch_table 存储分支事务元数据(branch_id、xid、资源ID、状态)
lock_table 存储全局锁信息(AT模式用)
distributed_lock 分布式锁表(集群选主等用) (CSDN Nacos 部署)

8.3 Raft 集群模式

Seata 2.1.0+ 支持原生 Raft 共识协议,TC 节点间通过 Raft 自动同步事务日志,无需依赖外部存储:

# application.yml
seata:
  store:
    mode: raft
    raft:
      clusterNodes: 192.168.1.101:8091,192.168.1.102:8091,192.168.1.103:8091
      group: default
      serverPort: 8091
  • 节点数:必须为奇数(3/5/7),避免脑裂
  • 优势:部署简单、运维成本低、不依赖外部中间件、数据强一致
  • 推荐:2.5.0+ 已优化事务大小检查和元数据同步,生产首选 (CSDN 生产)

8.4 注册中心与配置中心

Seata TC 支持多种注册中心和配置中心:

类型 支持的实现
注册中心 Nacos(推荐)、Eureka、Redis、ZooKeeper、Consul、etcd3、Sofa (CSDN 高可用)
配置中心 Nacos(推荐)、Apollo、ZooKeeper、etcd3、Consul

客户端和 TC 必须配置相同的 namespace + group,否则客户端无法发现 TC。

8.5 生产部署架构推荐

                    ┌─────────────┐
                    │  Nacos 集群  │ ← 注册中心+配置中心
                    └──────┬──────┘
                           │ 服务发现/配置下发
        ┌──────────────────┼──────────────────┐
        │                  │                  │
  ┌─────┴─────┐     ┌─────┴─────┐     ┌─────┴─────┐
  │ TC Node1  │     │ TC Node2  │     │ TC Node3  │  ← 3节点 Raft 集群
  │  (Leader) │────→│ (Follower)│←────│(Follower) │     (跨可用区部署)
  └───────────┘     └───────────┘     └───────────┘
        ↑                  ↑                  ↑
        └──────────────────┴──────────────────┘
                           │ Netty 通信
        ┌──────────────────┼──────────────────┐
        │                  │                  │
  ┌─────┴─────┐     ┌─────┴─────┐     ┌─────┴─────┐
  │ 微服务A    │     │ 微服务B    │     │ 微服务C    │  ← TM/RM 嵌入
  │ (订单服务) │     │ (库存服务) │     │ (账户服务) │
  └───────────┘     └───────────┘     └───────────┘

(CSDN 生产) (CSDN 高可用)

资源规划

  • TC Server:每节点 ≥2核4G,JVM -Xms2g -Xmx2g,使用 G1GC
  • Nacos 集群:≥3节点,2核4G
  • 跨可用区部署,网络延迟 <1ms
  • 生产节点数:3~5个 (CSDN 高可用)

9. Spring Cloud Alibaba 集成实战

9.1 核心依赖

Seata 2.x Maven 坐标已变更为 org.apache.seata(2.6.0 版本):

<properties>
    <seata.version>2.6.0</seata.version>
</properties>

<dependency>
    <groupId>org.apache.seata</groupId>
    <artifactId>seata-spring-boot-starter</artifactId>
    <version>${seata.version}</version>
</dependency>

(CSDN 生产)

9.2 客户端配置(application.yml)

seata:
  enabled: true
  tx-service-group: default_tx_group         # 事务分组名
  service:
    vgroup-mapping:
      default_tx_group: default              # 映射到 TC 集群名
  registry:
    type: nacos
    nacos:
      application: seata-server
      server-addr: 127.0.0.1:8848
      group: SEATA_GROUP
      namespace: ""
      username: nacos
      password: nacos
  config:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      group: SEATA_GROUP
      data-id: seataServer.properties
  client:
    rm:
      async-commit-buffer-limit: 10000       # 异步提交缓冲
      lock:
        retry-interval: 10                   # 锁重试间隔(ms)
        retry-times: 30                      # 锁重试次数
    tm:
      default-global-transaction-timeout: 60000  # 默认超时(ms)
      commit-retry-count: 3
      rollback-retry-count: 3

9.3 @GlobalTransactional 使用

@Service
@RequiredArgsConstructor
public class OrderService {

    private final OrderRepository orderRepository;
    private final ProductFeignClient productClient;
    private final AccountFeignClient accountClient;

    // 核心注解:开启全局事务
    @GlobalTransactional(rollbackFor = Exception.class, timeoutMills = 30000, name = "createOrder")
    public Order createOrder(CreateOrderDTO dto) {
        // 步骤1:本地操作 —— 创建订单
        Order order = orderRepository.save(buildOrder(dto));
        // 步骤2:远程调用 —— 扣减库存
        productClient.deductStock(dto.getProductId(), dto.getQty());
        // 步骤3:远程调用 —— 扣减余额
        accountClient.deductBalance(dto.getUserId(), order.getAmount());
        return order;
        // 任何步骤抛异常 → Seata 协调所有服务回滚
    }
}

(CSDN 面试题)

9.4 undo_log 建表(客户端)

每个参与 Seata AT 事务的业务数据库都必须建 undo_log 表(表结构见 §3.4)。

9.5 常见坑点与避坑

坑点 原因 解决方案 (腾讯云)
事务不回滚 方法非 public、异常被 catch 吞掉、未加 rollbackFor 方法必须 public;异常抛出不要内部吞;配置 rollbackFor=Exception.class
XID 未传递 自定义 Feign 拦截器覆盖了 Seata 自动传递 自定义拦截器中手动 RootContext.getXID() 放入 Header
数据源代理冲突 Druid/Sharding-JDBC 与 Seata 代理冲突 调整代理顺序,Seata 代理 ShardingJDBC 的数据源;关闭 Druid stat 监控 Servlet
事务超时 业务耗时超过默认 60s 设置合理 timeoutMills;优化慢 SQL;拆分长事务
高并发超卖 AT 模式脏读 + 未加行锁 库存扣减 SQL 加条件 WHERE stock >= ?;高并发用 TCC
嵌套 @GlobalTransactional 子方法重复开启全局事务 仅在顶层入口方法加 @GlobalTransactional,子方法自动继承 XID
undo_log 过大 日志未清理占满磁盘 定期清理(配置 logSaveDays=7);按时间分区
Seata 版本不兼容 Client/Server 版本差异 Client 与 Server 版本保持一致;Spring Cloud Alibaba 版本与 Seata 版本对齐

10. 生产环境最佳实践

10.1 性能优化

  1. 合理设置事务范围:仅将核心写操作纳入全局事务,非核心操作(发消息、记日志、通知)剥离到事务外或用本地事务
  2. 热点数据优化
    • 库存分桶:将单条库存记录分散为多条(如16个桶),通过哈希路由
    • 分段锁:自定义 LockStrategy 实现分段锁键 (掘金)
    • 热点场景用 TCC 模式替代 AT
  3. 异步提交:非核心链路开启 client.rm.async-commit-buffer-limit 增大异步缓冲区
  4. 批量操作:合并同源分支事务(2.6.0 已支持多数据源下同源分支事务自动合并)
  5. JVM 调优:TC Server 使用 G1GC,-Xms2g -Xmx2g -XX:G1HeapRegionSize=32m (CSDN 生产)
  6. 数据库连接池:合理配置 store.db.minConn=5, maxConn=30, maxWait=3000
  7. undo_log 索引ALTER TABLE undo_log ADD INDEX idx_xid (xid), ADD INDEX idx_branch_id (branch_id);

10.2 监控告警指标

通过 Prometheus + Grafana 监控 TC 集群核心指标 (CSDN 生产)

指标 告警阈值 说明
全局事务 QPS 超过单节点能力 80% 需扩容 TC
全局锁等待数 1分钟 >100 次 锁竞争严重,可能有热点
事务超时数 1分钟 >50 次 业务慢或锁等待过久
TC 节点存活数 < 集群数 50% 严重故障
事务回滚率 >5% 业务异常率高
undo_log 磁盘使用率 >80% 需要清理
JVM Full GC 频率 1小时 >5次 需调优内存

启用方式:

metrics.enabled=true
metrics.exporter-prometheus.enabled=true
metrics.exporter-prometheus.port=9898

10.3 故障排查常用手段

  1. XID 日志追踪:业务日志中打印 XID(RootContext.getXID()),通过 XID 串起全链路
  2. TC 控制台:Seata Console(默认端口 7091)查看全局事务状态、分支事务详情、Saga 状态机
  3. 查看锁表lock_table 中查看持锁事务,排查死锁和长时间持锁
  4. 查看事务表global_tablebranch_table 中按状态/时间查询异常事务
  5. 手动干预:二阶段回滚失败时,可通过控制台或管理 API 手动触发重试/删除异常事务
  6. 降级兜底:TC 不可用时,降级为本地事务 + MQ 最终一致方案 (腾讯云)

10.4 生产检查清单

  • ✅ TC 集群部署 ≥3 节点,跨可用区
  • ✅ 存储模式使用 raft 或 db(mysql 主从),禁止 file
  • ✅ 注册中心使用 Nacos 集群
  • ✅ undo_log 表已建索引,配置定期清理(保留7天)
  • ✅ TCC 模式开启 useTCCFence = true
  • ✅ @GlobalTransactional 仅加在顶层入口方法
  • ✅ 设置合理的超时时间(不要超过 60s)
  • ✅ 监控告警配置完整
  • ✅ 定期演练 TC 节点故障转移

11. 大厂高频面试题(30道)

以下题目来自美团、阿里、字节、京东等大厂真实面试场景,每题给出核心要点面试回答模板

Q1:介绍一下 Seata 的核心架构和三大角色?

核心要点:TC(事务协调者/Seata Server)维护全局事务状态、管理全局锁;TM(事务管理器/发起方)开启/提交/回滚全局事务、传播 XID;RM(资源管理器/参与方)管理分支事务、注册上报、执行提交回滚。流程:TM 向 TC 申请 XID → 沿调用链传播 XID → RM 向 TC 注册分支 → TM 结束时通知 TC → TC 驱动各分支提交或回滚。

面试模板

“Seata 有三大核心组件:TC 是独立部署的 Seata Server,是全局事务的大脑,负责生成 XID、维护事务状态、管理全局锁;TM 嵌入事务发起方应用,负责定义全局事务边界,通过 @GlobalTransactional 注解向 TC 申请开启、提交或回滚全局事务;RM 嵌入每个参与服务,负责分支事务的注册、状态上报和本地执行。整个流程是 TM 开启全局事务获得 XID,XID 沿 RPC 调用链传播到所有下游服务,各 RM 向 TC 注册分支,最后 TM 根据结果通知 TC 提交或回滚,TC 调度所有分支完成二阶段操作。”

Q2:Seata AT 模式的工作原理?(最高频)

核心要点:改进版两阶段提交。Phase 1:代理数据源拦截 SQL,查询前镜像(before image)→ 执行业务 SQL → 查询后镜像(after image)→ 生成 undo_log 写入回滚日志表 → 在同一个本地事务中提交业务数据和 undo_log → 申请全局锁 → 释放本地锁。Phase 2:成功则异步删除 undo_log 并释放全局锁;失败则根据 before image 生成反向 SQL 回滚,并做脏写校验(after image 与当前数据对比)。

面试模板

“AT 模式是 Seata 默认的无侵入分布式事务方案,核心是改进版两阶段提交。一阶段时,Seata 通过代理 DataSource 拦截业务 SQL,在执行前后分别查询修改前和修改后的数据快照(before/after image),将快照作为回滚日志写入 undo_log 表,然后在同一个本地事务中提交业务数据和回滚日志,立刻释放本地数据库锁,只向 TC 申请一个全局锁。二阶段如果全局成功,就异步删除 undo_log 释放全局锁;如果失败,就根据 undo_log 里的 before image 生成反向 SQL 回滚数据,并校验 after image 和当前数据是否一致,防止脏写。对比传统 2PC,它一阶段就提交了本地事务,不长时间持有数据库锁,所以性能很高。”

Q3:AT 模式如何实现写隔离?全局锁机制是什么?

核心要点:全局锁由 TC 集中管理,锁粒度是"表名+主键值"。一阶段本地事务提交必须先拿到全局锁,拿到后才提交本地事务;本地锁提交后立即释放,但全局锁持续持有到二阶段。其他全局事务修改同一行时必须等待全局锁释放,通过自旋重试获取。这保证了多个 Seata 全局事务之间不会发生脏写。

面试模板

“AT 模式的写隔离是通过全局锁实现的。全局锁由 TC Server 集中管理,锁的粒度是行级——通过 表名+主键值 构造锁键。流程是:一阶段本地事务提交前,RM 必须先向 TC 申请这行数据的全局锁,拿到锁后才能提交本地事务。本地事务一提交,数据库层面的行锁就立刻释放了,不会长时间占用数据库连接,但全局锁一直持有到二阶段结束。此时如果另一个全局事务也要修改同一行数据,它拿不到全局锁,会自旋重试(默认重试30次,每次间隔10ms),超时就回滚。这样保证了 Seata 管理的全局事务之间不会脏写。但注意,非 Seata 管理的本地事务不受全局锁约束,可能导致脏写。”

Q4:AT 模式的读隔离级别是什么?如何实现读已提交?

核心要点:AT 模式默认是读未提交(Read Uncommitted),因为一阶段已经提交了本地事务,其他本地事务可以读到中间状态数据。要实现读已提交,需要在查询语句上加 SELECT ... FOR UPDATE,Seata 会对这种语句也申请全局锁,如果全局锁被其他事务持有就等待,保证读到的一定是已全局提交的数据。但这会降低并发性能。

面试模板

“AT 模式默认的隔离级别是读未提交。原因是一阶段业务数据就已经提交到数据库了,在全局事务二阶段完成之前,其他本地事务可以读到这个中间状态。如果业务需要读已提交的隔离级别,可以在查询时使用 SELECT … FOR UPDATE,Seata 的数据源代理会识别这个语句,对查询也去申请全局锁。如果全局锁被其他全局事务持有,查询会释放本地锁重试等待,直到拿到全局锁才能读到数据,这就保证了读到的一定是已全局提交的数据。代价是性能下降,因为查询也会被锁阻塞。大多数场景下默认读未提交是可以接受的,因为全局锁持有时间很短。”

Q5:undo_log 是什么?表里有哪些字段?

核心要点:undo_log 是 AT 模式的核心,记录了数据修改前后的镜像。核心字段:branch_id(分支ID,主键)、xid(全局事务ID)、context(序列化方式等上下文)、rollback_info(LONGBLOB 类型,存 before/after image 的 JSON 序列化数据)、log_status(状态,0=正常,1=已删除)、log_created/log_modified(时间戳)。每个业务库都要建此表,有 (xid, branch_id) 唯一索引。

面试模板

“undo_log 是 AT 模式实现回滚的依据,每个参与分布式事务的业务数据库都必须创建这张表。核心字段包括:branch_id 是分支事务ID做主键,xid 是全局事务ID,context 记录序列化方式等上下文,rollback_info 是 LONGBLOB 类型存储 before image 和 after image 的序列化数据,log_status 标记状态,log_created 和 log_modified 是时间戳,还有一个 xid+branch_id 的联合唯一索引。一阶段时 Seata 自动写入回滚日志,二阶段提交时删除,回滚时用它生成反向 SQL。”

Q6:AT 模式二阶段回滚时的脏写校验是什么?

核心要点:回滚前 Seata 会用 undo_log 里保存的 after image 与数据库当前数据做对比。如果当前数据 ≠ after image,说明在 Seata 全局事务执行期间,有非 Seata 控制的操作(如直接 DBA 修改、另一个本地事务绕过 Seata)修改了数据,此时回滚会导致数据错乱。Seata 的处理是:不自动回滚,打印错误日志,转人工介入处理。

面试模板

“脏写校验是 AT 模式回滚时的安全机制。在二阶段回滚时,Seata 会先拿 undo_log 里保存的 after image(也就是一阶段提交后的数据快照)跟数据库当前的这行数据做对比。如果两者不一致,说明在 Seata 全局事务执行过程中,有非 Seata 控制的操作(比如数据库管理员直接改了数据、或者其他没被 Seata 管理的本地事务修改了)修改了这行数据。这时候如果强行用 before image 回滚,就会覆盖掉别人的修改,造成数据错误。Seata 的策略是不自动回滚,而是记录错误日志、告警,转人工处理。这也说明 AT 模式要求所有相关写操作都必须走 Seata 管控。”

Q7:TCC 模式的原理?和 AT 模式的区别?

核心要点:TCC 是业务层两阶段:Try(资源预留/检查+冻结)、Confirm(确认执行/用冻结资源真正扣减)、Cancel(取消/释放冻结资源)。与 AT 区别:TCC 不依赖数据库事务和 undo_log,不持有全局锁,性能更高(TCC TPS 约为 AT 的2倍,秒杀场景可达12倍);但业务侵入性高,需要为每个操作编写三个方法;TCC 可以操作非关系型资源(Redis、MQ、API),AT 只能操作关系型数据库。

面试模板

“TCC 模式是业务层面的分布式事务方案,将每个操作拆成 Try、Confirm、Cancel 三个方法。Try 阶段做资源检查和预留,比如扣库存不直接扣,而是把库存从’可用’转移到’冻结’;Confirm 阶段在所有分支 Try 成功后执行,把冻结的资源真正扣减掉;Cancel 阶段在任一失败时释放冻结资源。和 AT 模式的核心区别:第一,TCC 不依赖数据库事务和 undo_log,完全由业务代码控制;第二,TCC 不需要全局锁,性能比 AT 高很多,压测下 TPS 大约是 AT 的两倍,秒杀场景可达12倍;第三,TCC 可以操作 Redis、MQ、第三方 API 等非关系型资源,而 AT 只能操作支持 JDBC 的关系库;代价是侵入性高,每个接口要写三个方法。核心交易链路如支付、秒杀用 TCC,普通业务用 AT。”

Q8:TCC 模式的空回滚、悬挂、幂等问题是什么?怎么解决?

核心要点

  • 空回滚:Try 没收到(网络丢包),但 Cancel 到了,直接执行 Cancel 会多释放资源。解决:Cancel 前查事务记录表,无 Try 记录则直接返回成功(不做操作)。
  • 悬挂:空回滚执行完后,迟到的 Try 才到达,冻结了资源但再也没人处理,资源永久泄漏。解决:空回滚时插入 SUSPENDED 标记,Try 执行前检查到该标记则拒绝执行。
  • 幂等:网络抖动导致 TC 重发 Confirm/Cancel,重复执行导致数据错误。解决:通过事务状态表,Confirm/Cancel 执行前检查状态,已完结则直接返回。
  • Seata 1.5.1+ 提供 TCC Fence(篱笆)机制:用一张 tcc_fence_log 表和状态机自动解决这三个问题,只需在注解上加 useTCCFence = true,无需手动编码。

面试模板

“TCC 模式在网络不可靠时会遇到三个经典问题。第一是空回滚:Try 因网络问题没到达,但 Cancel 到了,这时候如果直接执行 Cancel 释放资源,就会凭空多出资源造成资损。解决方案是 Cancel 执行前先查事务控制表,没有对应的 Try 记录就直接返回成功,不做操作。第二是悬挂:这是空回滚的孪生问题,空回滚执行完了,迟到的 Try 才到达并冻结了资源,但全局事务已经结束,没人来 Confirm 或 Cancel,资源就永久悬挂了。解决办法是空回滚时插入一条 SUSPENDED 状态记录,迟到的 Try 执行前发现这个标记就拒绝执行。第三是幂等:网络重试可能导致 Confirm 或 Cancel 被重复调用,解决办法是用状态表控制,执行前检查状态是否已完结,已完结就直接返回。Seata 从 1.5.1 版本开始提供了 TCC Fence 篱笆机制,通过一张 tcc_fence_log 表在框架层自动处理这三个问题,只要在 @TwoPhaseBusinessAction 注解上设置 useTCCFence=true,不需要业务手动编写防护逻辑,生产环境必须开启。”

Q9:SAGA 模式的原理?适用什么场景?

核心要点:SAGA 是长事务方案,将长事务拆成一系列本地事务,每个本地事务有对应的补偿事务。正向执行所有步骤,任一步骤失败则反向执行已成功步骤的补偿。Seata 提供状态机引擎(JSON定义流程,支持可视化编排,支持选择/并发/子流程/异常捕获)和注解两种方式。特点:无全局锁、性能极高、无隔离性(中间状态对外可见)、补偿可能失败需人工兜底。适用:订单履约、跨部门长流程、服务编排等长事务场景。

面试模板

“SAGA 模式是 Seata 提供的长事务解决方案,核心思想是把长事务拆成多个本地短事务,每个本地事务都有对应的补偿操作。执行时按顺序正向调用每个本地事务,如果某个失败了,就从失败点反向调用前面已成功的事务的补偿操作,最终达到一致。Seata 的 SAGA 提供状态机引擎,通过 JSON 定义服务调用流程和补偿关系,支持可视化设计器,还能做条件分支、并发、子流程、异常捕获。它的特点是一阶段直接提交本地事务,没有全局锁,性能极高;缺点是没有隔离性,其他事务能看到中间状态,而且补偿操作可能失败,需要人工干预兜底。SAGA 适合业务流程长的场景,比如订单履约——创建订单、扣库存、扣款、创建物流、发通知,这种跨越多个服务、执行时间长的流程。”

Q10:XA 模式的原理?和 AT 模式的区别?

核心要点:XA 基于数据库原生 XA 协议实现强一致两阶段提交。Phase 1 执行 SQL 后 XA PREPARE(持久化但不提交,一直持有数据库锁和连接),Phase 2 所有分支 Prepare 成功才 XA COMMIT,否则 XA ROLLBACK。与 AT 对比:XA 是强一致(ACID),AT 是最终一致;XA 全程持数据库锁导致性能极低,AT 一阶段就释放本地锁性能高;XA 无侵入但仅支持 XA 协议数据库,AT 需要 undo_log 表但支持更多数据库。XA 生产中极少使用。

面试模板

“XA 模式是基于数据库原生 XA 协议的强一致性两阶段提交方案。Seata 作为协调者,一阶段让每个 RM 在 XA 分支里执行业务 SQL,执行完后做 XA PREPARE,这时候数据已经持久化但不提交,数据库锁和连接一直被持有,等待 TC 的二阶段指令。二阶段如果所有分支都 Prepare 成功,就通知所有分支 XA COMMIT;如果有失败就全部 XA ROLLBACK。和 AT 模式的核心区别:第一,XA 是强一致性保证 ACID,AT 是最终一致性;第二,XA 在整个两阶段过程中一直持有数据库锁和连接,并发性能很低,容易导致连接池耗尽,而 AT 一阶段就提交本地事务释放本地锁,性能接近本地事务;第三,XA 不需要 undo_log 但要求数据库支持 XA 协议,AT 支持更多数据库。生产中 XA 很少用,仅在强一致且并发极低的场景如银行批处理才考虑。”

Q11:Seata 四种模式如何选型?

核心要点:根据一致性要求、事务长度、并发量、开发成本综合判断。大厂选型原则:强一致短事务且高并发核心链路(支付/秒杀)→ TCC;长事务/服务编排(订单履约/物流)→ SAGA;低并发简单跨库(管理后台)→ AT(默认首选);强一致且低并发(金融批处理)→ XA(极少用)。总原则:能用最终一致就不用强一致,Seata 有全局锁和网络开销,会降低吞吐量。

面试模板

“Seata 四种模式的选型主要看四个维度:一致性要求、事务长度、并发压力和开发成本。首先,常规业务和内部管理系统首选 AT 模式,零侵入、开发成本最低,性能也能满足大多数场景。其次,高并发核心交易链路比如支付、秒杀库存扣减,AT 模式的全局锁会成为瓶颈,这时候用 TCC 模式,通过业务层资源预留不持有全局锁,性能可达 AT 的数倍,但需要开发三个方法,成本高。第三,长事务场景比如订单履约这种跨多服务、执行时间长的流程,用 SAGA 模式,无锁性能好,还支持服务编排,但补偿逻辑需要自己写,且没有隔离性。第四,XA 模式是强一致性但性能很差,生产几乎不用,只在金融批处理等特殊场景考虑。大厂的核心原则是’能用最终一致就不用强一致’,Seata 本身会引入全局锁和网络开销,在 MQ 最终一致能解决的场景就不要上 Seata。”

Q12:Seata 的 XID 是什么?如何在分布式调用链中传播?

核心要点:XID 是全局事务唯一标识,格式一般是 ip:port:sequence,由 TC 生成。XID 需要沿完整的 RPC 调用链传播到所有下游服务,下游服务根据 XID 向 TC 注册分支事务。在 Spring Cloud/Dubbo 中 Seata 的 starter 自动通过拦截器传递 XID(HTTP Header / Dubbo RpcContext),但如果自定义了 Feign 拦截器或使用了非标准 RPC,需要手动从 RootContext.getXID() 获取 XID 放入请求上下文传递。

面试模板

“XID 是全局事务的唯一标识,由 TC 在 TM 开启全局事务时生成,格式类似 ip:port:序列号。它需要在整个分布式调用链中传播,让所有下游服务知道自己属于哪个全局事务,才能正确地向 TC 注册分支事务。在 Seata 的 Spring Boot Starter 中,针对 Feign、Dubbo、RestTemplate 等主流 RPC 框架都提供了自动拦截器,会自动从 RootContext 中获取 XID 放入请求头或 RPC 上下文,服务提供方收到请求后自动绑定 XID 到当前线程上下文。但如果用了自定义的 RPC 框架或者自己写了 Feign 拦截器覆盖了默认行为,就需要手动调用 RootContext.getXID() 获取 XID,放到请求 Header 里传递,下游再通过 RootContext.bind() 绑定,否则下游服务的分支事务不会注册到全局事务中,回滚时就失效了。”

Q13:Seata AT 模式和 Spring @Transactional 的区别?

核心要点

  • @Transactional本地事务,只能管理单个数据库连接内的操作,基于数据库 ACID 特性实现
  • @GlobalTransactional分布式全局事务,可以跨多个服务/数据库,通过 TC 协调
  • 本地事务基于数据库锁和 undo log(数据库自己的 redo/undo log)实现原子性
  • Seata 全局事务通过全局锁 + undo_log(Seata 自己的表)实现跨服务原子性
  • @GlobalTransactional 内部可以嵌套 @Transactional,Seata 负责全局协调,每个分支内部仍是本地事务
  • 本地事务是强一致,Seata AT 是最终一致(接近强一致)

面试模板

“@Transactional 是 Spring 的本地事务注解,只能管理单个数据库连接内的操作,底层依赖数据库自身的 ACID 特性和锁机制实现原子性。而 @GlobalTransactional 是 Seata 的分布式事务注解,可以跨多个微服务、多个数据库,通过独立部署的 TC 协调器来管理全局事务的提交和回滚。两者的关键区别:第一,作用范围不同,本地事务只能控制一个数据源内的操作,全局事务跨服务跨库;第二,实现机制不同,本地事务靠数据库本身的锁和事务日志,Seata AT 靠全局锁和自己的 undo_log 表实现跨节点回滚;第三,一致性级别不同,本地事务是强一致 ACID,AT 模式是最终一致但接近强一致。两者可以嵌套使用:@GlobalTransactional 标注在方法上时,内部每个分支的本地操作仍然使用 @Transactional 或 Seata 自动代理的本地事务保证原子性,Seata 负责跨分支的全局协调。”

Q14:Seata TC Server 的存储模式有哪些?生产环境怎么选?

核心要点:四种存储模式——file(本地文件,仅开发用,不支持集群)、db(MySQL 等共享数据库,强一致,生产主流)、redis(Redis 存储,性能高但最终一致)、raft(Seata 2.1+ 内置 Raft 共识,3+ 节点自动同步,无需外部存储,2.5+ 生产成熟)。生产选择:推荐 Raft 模式(部署运维简单、强一致、性能好),其次是 DB 模式(MySQL主从),Redis 模式用于对一致性要求略低的高并发场景,严禁 file 模式。

面试模板

“Seata TC 支持四种存储模式。第一种是 file 模式,数据存本地文件,性能高但不支持集群,只能单机开发测试用。第二种是 db 模式,把全局事务、分支事务、全局锁都存在共享数据库 MySQL 里,通过数据库事务保证一致性,支持集群,这是最经典的生产方案,需要自己维护 MySQL 高可用。第三种是 redis 模式,数据存 Redis,性能最高,但 Redis 有异步落盘风险是最终一致,适合对性能极致要求且容忍少量数据丢失的场景。第四种是 raft 模式,Seata 从 2.1 版本开始内置支持,3个或以上 TC 节点通过 Raft 共识协议自动同步事务日志,不需要外部数据库或 Redis,部署简单且强一致,从 2.5 版本开始优化成熟,是目前最推荐的生产方案。生产环境严禁用 file 模式,推荐优先用 raft,其次是 db 模式搭配 MySQL 主从。”

Q15:Seata 如何保证高可用?

核心要点:TC 集群部署(3/5节点,奇数,跨可用区)+ 共享存储(Raft 或 DB/Redis)+ 注册中心(Nacos 集群实现服务发现和负载均衡)+ 配置中心(Nacos 动态配置)+ 监控告警 + 故障转移演练。客户端通过事务分组(vgroupMapping)映射到 TC 集群,TC 节点故障后客户端自动切换到其他节点。TC 节点之间通过共享存储/Raft 同步事务状态,任何节点挂掉不丢失事务数据。

面试模板

“Seata 的高可用从多个层面保证。首先是 TC 层必须集群部署,生产环境至少 3 个节点(奇数个防止 Raft 脑裂),跨可用区部署避免单机故障;节点间通过 Raft 协议或共享数据库同步事务状态,任何一个节点挂掉事务数据不丢失,客户端通过 Nacos 注册中心自动感知并切换到健康节点。其次注册中心和配置中心本身也要集群化(Nacos 集群),不能成为单点。第三是存储层高可用:用 Raft 模式内置副本,或者 DB 模式用 MySQL 主从复制。第四是客户端配置事务分组 vgroupMapping,通过逻辑分组名映射到 TC 集群,实现多集群隔离和故障切换。最后要有完整的监控告警(Prometheus+Grafana 监控事务QPS、锁等待、回滚率等指标),并定期进行故障转移演练。”

Q16:Seata 和消息队列实现最终一致性的区别?怎么选型?

核心要点:Seata 提供的是实时一致性(全局锁保证没有脏写,AT 接近强一致,TCC 是预留资源级隔离),适合必须同时成功/失败的核心操作(如下单+扣库存+扣余额),有性能开销(全局锁、网络通信、undo_log IO)。MQ 实现的是最终一致性(本地消息表/事务消息),性能高吞吐大,但存在短暂不一致的时间窗口,适合允许异步一致性的操作(如发优惠券、更新积分、发送通知)。选型核心判断:操作是否需要"立刻一致"?需要则 Seata,允许延迟则 MQ。

面试模板

“Seata 和消息队列是两种不同层次的一致性方案。Seata 追求的是实时一致性,通过全局锁协调多个分支要么都成功要么都回滚,适合核心交易链路——比如下单必须同时扣库存和扣余额,任何一个失败都不能留下脏数据,这时候必须用 Seata。但 Seata 会引入全局锁竞争、网络通信和 undo_log 的 IO 开销,会降低系统吞吐量。消息队列实现的是最终一致性,通过本地消息表或者 RocketMQ 事务消息保证消息一定被消费,但下游消费存在延迟,短暂时间内数据是不一致的,不过性能极高、吞吐量大,适合非核心操作——比如下单成功后发优惠券、更新积分、发短信通知,这些允许延迟几秒甚至几分钟的操作。选型的核心判断是:'这个操作是否需要立刻一致?‘核心资金操作必须立刻一致用 Seata,非核心通知类操作允许延迟用 MQ。大厂的原则是’能用最终一致就不用强一致’。”

Q17:Seata AT 模式在高并发秒杀场景下有什么问题?怎么优化?

核心要点:问题:①全局锁竞争严重,热点商品库存行成为锁竞争焦点,可能导致全链路超时雪崩;②undo_log 写放大,IOPS 高;③默认读未提交可能导致超卖。优化:①库存分桶,将一个 SKU 的库存分散到 N 条记录,哈希路由到不同桶,将锁粒度从"单商品"变为"单桶",并发度提升 N 倍;②混合模式,热点扣库存用 TCC(无全局锁),其他操作用 AT;③前置流量过滤,用 Redis 分布式锁限流,只有拿到 Redis 锁的请求才进 Seata 事务;④SQL 层加防超卖条件 WHERE stock >= ?;⑤调优锁重试参数。

面试模板

“AT 模式在秒杀场景下的核心问题是全局锁瓶颈。热点商品的库存行成为全局锁竞争的焦点,QPS 很高时所有请求都在争抢这一把锁,锁等待超过几秒就会导致全链路超时甚至雪崩;另外每个操作都要写 undo_log,数据库 IOPS 压力很大。优化策略有几个:第一,库存分桶——把一个 SKU 的总库存分散到 16 或 32 条记录里,扣减时用用户 ID 或商品 ID 哈希选择一个桶操作,把一把全局锁分散成多把,并发能力提升数十倍;第二,混合事务模式,热点的库存扣减用 TCC 模式(不持有全局锁),非热点的优惠劵锁定等操作用 AT;第三,在 Seata 之前用 Redis 分布式锁做前置限流,减少进入 Seata 事务的请求量;第四,扣减库存 SQL 必须加防御条件 WHERE stock >= count,防止数据库层面超卖;第五,适当调优锁重试间隔和次数参数。终极方案是核心秒杀链路全部用 TCC。”

Q18:Seata 的全局锁会死锁吗?和数据库死锁的区别?

核心要点:全局锁由 TC 集中管理,理论上不会发生数据库层面的死锁(因为全局锁获取有超时机制,超时后直接回滚释放锁,不会循环等待)。但可能出现锁等待超时(类似长时间阻塞):事务A持有行1锁等待行2锁,事务B持有行2锁等待行1锁,双方都等待对方释放,最终超时回滚。Seata 不做全局死锁检测,依赖超时机制打破。与数据库死锁区别:数据库有死锁检测机制主动回滚代价小的事务,Seata 依赖超时(默认30次重试×10ms=300ms后超时回滚)。

面试模板

“Seata 的全局锁不会像数据库那样出现经典的死锁循环等待,因为 TC 集中管理所有全局锁,并且获取全局锁有超时机制——如果重试一定次数仍拿不到锁就会回滚当前事务释放自己持有的锁,超时机制打破了循环等待。但在高并发下可能出现长时间锁等待,比如事务A持有了行1的锁在等行2的锁,事务B反过来持有行2等行1,双方都在重试直到超时,类似死锁效果但最终会超时回滚不会永久阻塞。和数据库死锁的区别是:数据库有专门的死锁检测机制(如 waits-for graph 检测环),会主动选择代价最小的事务回滚;Seata 没有死锁检测,依赖客户端的锁重试超时机制兜底,默认重试30次每次10ms,大约300ms超时就回滚。生产中应该尽量设计避免一个全局事务内同时操作多行会产生交叉加锁顺序的场景。”

Q19:@GlobalTransactional 注解加在什么位置?有哪些注意事项?

核心要点:必须加在事务发起方的 public 方法上(一般是入口 Service 方法或 Controller 调用的最顶层业务方法)。注意事项:①方法必须是 public(Spring AOP 代理要求);②不要在同类中自调用(this 调用不经过代理,注解失效);③不要在子方法/下游服务重复加 @GlobalTransactional(会造成嵌套事务混乱,子方法自动继承 XID);④必须指定 rollbackFor = Exception.class(默认只回滚 RuntimeException);⑤timeoutMills 设置合理超时;⑥异常不能被 try-catch 吞掉,必须抛出才能触发回滚。

面试模板

“@GlobalTransactional 必须加在分布式事务发起方的 public 方法上,也就是整个全局事务链路最顶层的入口方法,比如订单服务的 createOrder 方法。使用有几个关键注意事项:第一,方法必须是 public,因为 Seata 基于 Spring AOP 动态代理,private/protected 方法注解不生效;第二,不能在同一个类里进行方法自调用,this.xxx() 不会经过代理对象,注解失效;第三,子方法和下游服务不要重复加 @GlobalTransactional,否则可能造成事务嵌套混乱,子方法会自动继承上游的 XID,加入同一个全局事务,不需要重复声明;第四,要显式配置 rollbackFor=Exception.class,因为默认只对 RuntimeException 回滚,检查异常不会触发回滚;第五,异常不能被内部 try-catch 吞掉,必须向上抛出才能触发全局回滚;第六,设置合理的 timeoutMills,不要让长时间运行的事务持有全局锁。”

Q20:Seata AT 模式和传统 2PC(XA)有什么本质区别?为什么 AT 性能更高?

核心要点:传统 2PC(XA)在 Prepare 阶段就锁定资源(数据库锁+连接),所有分支都 Prepare 完才能 Commit/Rollback,锁持有时间 = 整个事务执行时间(包含所有分支的执行 + 网络延迟),阻塞严重。Seata AT 在一阶段就提交本地事务释放数据库锁,只持有一个轻量级的全局锁在 TC 侧,二阶段提交是异步清理(删除 undo_log)极快,回滚通过 undo_log 补偿。本质差异:传统 2PC 是"预留资源→等所有人都准备好→一起提交"(同步阻塞),AT 是"先提交再说,失败了用日志补偿"(异步补偿)。

面试模板

“Seata AT 和传统 XA 两阶段提交的本质区别在于锁的持有策略。传统 2PC 在 Prepare 阶段就锁定了所有资源——数据库行锁和连接都被一直持有,直到所有参与者都 Prepare 完,协调者才发 Commit 指令,这个过程中锁持有时间等于整个分布式事务的执行时间,包含所有分支的业务执行加多次网络往返,阻塞非常严重。而 Seata AT 的核心创新是一阶段就直接提交了本地事务,数据库层面的行锁一提交就释放了,不会长时间占用数据库连接,只在 TC 侧持有一个全局锁保证写隔离。二阶段如果是提交,就异步删除 undo_log,非常快;如果是回滚,通过 undo_log 里的 before image 生成反向 SQL 补偿。简单说,传统 2PC 是’先锁资源,等所有人准备好再提交’,是悲观阻塞的;AT 是’先提交了再说,失败了有日志能补偿回去’,是乐观补偿的,所以性能接近本地事务。”

Q21:CAP 定理下 Seata 是什么立场?

核心要点:CAP 定理:在分布式系统中,一致性©、可用性(A)、分区容错性(P)三者不可兼得。在微服务中 P 是必须的,只能在 C 和 A 之间权衡。

  • XA 模式:选择 CP,强一致性,但在协调者故障或网络分区时会阻塞牺牲可用性
  • AT 模式:基本是 CP,全局锁实现写隔离(接近强一致),但 TC 故障时事务无法继续牺牲可用性;默认读未提交,一阶段提交后有短暂不一致窗口
  • TCC 模式:介于 CP 和 AP 之间,通过业务层资源预留可以控制一致性和可用性的权衡
  • SAGA 模式:选择 AP,高可用,最终一致性,不保证强一致

Seata 的多模式设计本质是给开发者在 C-A 之间做权衡的工具。

面试模板

“根据 CAP 定理,分布式系统在分区容错 P 必须保证的前提下,只能在一致性 C 和可用性 A 之间权衡。Seata 提供多种模式正是为了让开发者做不同的权衡。XA 模式是 CP 模型,追求强一致性,但在 TC 故障或网络分区时事务会阻塞牺牲可用性。AT 模式基本也是 CP,通过全局锁保证写隔离接近强一致,但默认读未提交,一阶段到二阶段之间存在短暂不一致窗口,TC 不可用时事务无法执行。TCC 模式介于 CP 和 AP 之间,可以通过业务设计灵活控制。SAGA 模式是 AP 模型,高可用、最终一致,不保证全局隔离。Seata 的价值就在于提供多模式让我们根据业务场景选合适的 C/A 平衡点,而不是一刀切。”

Q22:Seata AT 模式支持哪些数据库?为什么只能用在关系型数据库?

核心要点:AT 模式依赖关系型数据库的 ACID 特性,需要通过 JDBC 拦截 SQL 并查询前后镜像,需要本地事务保证业务数据和 undo_log 原子提交。支持:MySQL、PostgreSQL、Oracle、MariaDB、达梦(DM)、PolarDB-X 2.0、OceanBase 等支持 JDBC 和本地事务的关系型数据库。不支持 Redis、MongoDB、HBase 等 NoSQL,因为它们没有标准 SQL 无法解析前后镜像,也不支持本地 ACID 事务来保证 undo_log 和业务数据的原子写入。

面试模板

“Seata AT 模式目前支持 MySQL、PostgreSQL、Oracle、MariaDB、达梦、PolarDB-X 等主流关系型数据库,本质原因是 AT 模式的实现机制强依赖关系型数据库的三个特性:第一,必须支持 JDBC 访问,Seata 才能通过代理数据源拦截 SQL 并解析表名、条件、参数;第二,必须能够通过 SELECT 查询修改前和修改后的数据镜像,需要标准 SQL 查询能力;第三,必须支持本地 ACID 事务,才能保证业务数据更新和 undo_log 写入在同一个事务里原子提交,否则如果业务数据写成功了但 undo_log 写失败,回滚就没有依据。Redis、MongoDB 这类 NoSQL 没有标准 SQL 接口,Seata 无法自动解析和生成回滚信息,也无法保证原子写入,所以 AT 模式不能用在这些数据库上,这种场景要选 TCC 模式。”

Q23:Seata 客户端和服务端版本不兼容会怎样?如何避免?

核心要点:版本不兼容可能导致:协议不一致(Netty 通信协议变化)、序列化方式不同(如 hessian/fst/kryo 不匹配)、配置项变更导致启动失败、事务状态处理逻辑差异导致异常。Seata 2.x 相比 1.x 有较大变更(groupId 变更、配置格式变化、TCC 注解变化、Saga 解耦 Spring等)。避免方案:客户端和服务端使用完全相同的大版本(推荐同为 2.6.0);升级时先升级 Server 再升级 Client(Server 通常做了向下兼容);参考官方版本兼容性矩阵;Spring Cloud Alibaba 版本要与 Seata 版本对应。

面试模板

“Seata 客户端和服务端版本不一致会导致一系列问题:Netty 通信协议变化会导致 RPC 调用失败,序列化方式不匹配会导致消息反序列化异常,配置项的增减可能导致客户端或服务端启动失败,事务状态码或处理逻辑的差异可能导致事务悬挂或异常回滚。特别是 Seata 从 1.x 升级到 2.x(进入 Apache 孵化器后),Maven groupId 从 io.seata 变成了 org.apache.seata,配置文件格式也有变化,是一个较大的 breaking change。避免方案是客户端和服务端保持相同的大版本,最好是完全相同的小版本号,比如都用 2.6.0;升级时先升级 Server 再升级 Client,因为 Server 通常会做向下兼容;同时 Spring Cloud Alibaba 的版本也要和 Seata 版本对齐,可以参考官方发布的版本兼容矩阵。”

Q24:TCC 模式下 Try 阶段的资源预留应该怎么设计?举个实际例子。

核心要点:资源预留的核心是"冻结而非扣减"——Try 阶段不真正消耗资源,而是将资源从"可用"状态转移到"冻结"状态,确保资源不会被其他事务占用,但也不真正消耗;Confirm 阶段将冻结转为正式消耗;Cancel 阶段将冻结恢复到可用。以账户为例:表中有 balance(可用余额)和 frozen(冻结余额)两个字段,Try:UPDATE account SET balance = balance - ?, frozen = frozen + ? WHERE id = ? AND balance >= ?;Confirm:UPDATE account SET frozen = frozen - ? WHERE id = ?;Cancel:UPDATE account SET balance = balance + ?, frozen = frozen - ? WHERE id = ?。关键:Try 阶段的冻结操作必须在同一个本地事务中完成,且通过条件判断(如 balance >= ?)保证业务合法性。

面试模板

“TCC Try 阶段的核心设计原则是’冻结不扣减’,不能直接把资源扣掉,而是把资源从可用状态转移到冻结中间状态。以账户扣款为例,账户表需要有 balance(可用余额)和 frozen(冻结余额)两个字段。Try 阶段执行的 SQL 是 ‘UPDATE account SET balance = balance - 扣减金额, frozen = frozen + 扣减金额 WHERE user_id = ? AND balance >= 扣减金额’,这条 SQL 同时做了三件事:检查余额是否充足(WHERE 条件)、减少可用余额、增加冻结余额。因为是在一个本地事务里原子执行,所以不会出现超扣。Confirm 阶段只需要 ‘UPDATE account SET frozen = frozen - 扣减金额’,把冻结的金额扣减掉,不再动可用余额。Cancel 阶段执行 ‘UPDATE account SET balance = balance + 扣减金额, frozen = frozen - 扣减金额’,把冻结金额退回可用余额。库存的设计类似:stock 表有 available_stock 和 frozen_stock 字段,Try 冻结库存,Confirm 扣减冻结,Cancel 释放冻结。”

Q25:Seata 中事务分组(tx-service-group / vgroupMapping)是什么?为什么需要它?

核心要点:事务分组是 Seata 的逻辑概念,用于将客户端的事务请求映射到具体的 TC 集群。客户端配置 tx-service-group: default_tx_group,然后通过 vgroupMapping.default_tx_group = seata-server-cluster-A 映射到具体集群名。TC 注册到 Nacos 时使用集群名(如 cluster: default)。价值:①多集群隔离:不同业务组可映射到不同 TC 集群,实现资源隔离和故障隔离;②快速容灾切换:TC 集群故障时只需修改配置中心的 vgroupMapping 值即可切换到备用集群,无需重启客户端;③环境隔离:开发/测试/生产可使用不同分组映射到不同 TC。

面试模板

“事务分组是 Seata 中一个非常重要的逻辑概念,它解决了客户端如何找到 TC 集群的问题,同时提供了容灾切换能力。客户端配置一个 tx-service-group 名称,比如 default_tx_group,然后在配置中心配置一个映射关系 vgroupMapping.default_tx_group = 某个TC集群名,客户端通过这个映射找到 Nacos 中对应的 TC 服务。这样设计的好处有三个:第一是多集群隔离,不同业务可以用不同的事务组映射到不同的 TC 集群,避免核心业务和非核心业务互相影响;第二是快速容灾,当某个 TC 集群故障时,只需在配置中心修改 vgroupMapping 的值,把事务组映射到备用 TC 集群,客户端动态感知配置后就会切换到备用集群,不需要重启;第三是环境隔离,开发、测试、生产可以配置不同的分组映射到各自的 TC 环境。这是 Seata 高可用架构中的关键设计。”

Q26:Seata 二阶段提交失败(比如 RM 宕机了)怎么办?

核心要点:Seata 有重试机制:TC 会持续重试下发 Commit/Rollback 指令,直到 RM 成功响应(默认有最大重试次数配置,但实际可配置为无限重试)。RM 端实现了幂等性:重复的 Commit/Rollback 请求不会导致数据错误(AT 模式通过 undo_log 状态判断,TCC Fence 通过状态机控制)。如果 RM 长时间不可恢复:①事务日志会保留在 TC 存储中;②通过 Seata Console 或管理 API 可以手动干预(删除异常事务、跳过失败分支);③生产中需要告警及时介入,极端情况下通过数据修复脚本处理。Seata 设计为最终一定会完成提交或回滚,不会留下不一致状态。

面试模板

“Seata 处理二阶段失败的核心机制是重试加幂等。TC 在下发 Commit 或 Rollback 指令后,如果没有收到 RM 的成功响应,会持续重试发送(可以配置重试次数,生产通常设置较大值或无限重试)。RM 端的二阶段操作是幂等的——AT 模式通过 undo_log 的 log_status 字段判断是否已经处理过,重复请求直接返回成功;TCC 模式通过 TCC Fence 的状态机保证重复调用安全。如果某个 RM 长时间宕机无法恢复,TC 会一直保留该事务的状态并定期重试,同时监控系统应该产生告警。恢复后 RM 启动时会检查是否有未完成的分支事务并继续处理。极端情况下管理员可以通过 Seata Console 查看异常事务,手动触发重试或人工介入数据修复。整体设计保证事务最终一定会完成,不会永久悬挂在中间状态。”

Q27:Seata 如何和 Spring Cloud Alibaba 整合?关键配置有哪些?

核心要点:①引入 seata-spring-boot-starter 依赖(2.x 使用 org.apache.seata groupId);②每个业务库创建 undo_log 表(AT模式)和 tcc_fence_log 表(TCC模式);③配置文件中指定 tx-service-group、registry(注册中心 nacos 地址/namespace/group)、config(配置中心 nacos/data-id);④TC Server 端配置 Nacos 注册和存储模式(raft/db);⑤配置中心 Nacos 中导入 seataServer.properties(包含 store 配置、事务参数等);⑥在业务入口方法加 @GlobalTransactional;⑦Feign/Dubbo 调用自动传递 XID。

面试模板

“Spring Cloud Alibaba 整合 Seata 分几步。第一步,每个微服务引入 seata-spring-boot-starter 依赖,注意 2.x 版本的 groupId 是 org.apache.seata;第二步,每个业务数据库要创建 undo_log 表(AT 模式必需)和 tcc_fence_log 表(TCC 模式用);第三步,配置 application.yml,核心配置包括:tx-service-group 指定事务分组名,registry 配置 Nacos 地址和 namespace/group 用于服务发现,config 配置 Nacos 地址和 data-id 用于拉取 TC 端配置,客户端参数包括锁重试次数、事务超时时间等;第四步,部署 Seata Server 集群,配置 Nacos 注册和存储模式(推荐 Raft),并在 Nacos 配置中心导入 seataServer.properties 配置文件;第五步,在分布式事务的入口方法加 @GlobalTransactional 注解开启全局事务。Seata Starter 会自动通过 Feign 和 Dubbo 的拦截器传递 XID,不需要额外编码。”

Q28:Seata 生产环境遇到过哪些坑?怎么解决的?

核心要点:综合常见生产问题:

  1. 全局锁竞争导致超时→热点分桶、TCC 混合模式、缩短事务
  2. undo_log 表膨胀→配置定期清理(logSaveDays=7)、分区表
  3. XID 未传递导致回滚失效→排查自定义拦截器、日志里打印 XID 确认
  4. 数据源代理冲突(Druid/Sharding-JDBC)→调整代理顺序
  5. TC 单点故障→集群部署+Raft
  6. 事务不回滚→检查注解位置、异常是否抛出、rollbackFor 配置
  7. 大字段/批量更新导致 undo_log 过大→配置 undo.compress.threshold 开启压缩、避免事务内批量更新大数据量
  8. 长事务导致全局锁长期持有→设置合理超时、拆分事务

面试模板

“生产环境比较常见的坑有几个。第一是热点数据的全局锁竞争,比如爆款商品扣库存,所有请求都在抢一把锁,导致超时雪崩,我们用库存分桶加混合模式(热点用 TCC)解决。第二是 undo_log 表数据膨胀不清理,时间长了磁盘满查询慢,配置 logSaveDays=7 天自动清理,或者按时间分区。第三是自定义 Feign 拦截器把 Seata 的 XID 传递给覆盖了,导致下游服务分支事务没注册到全局事务中,回滚失效,解决办法是在自定义拦截器中显式从 RootContext 获取 XID 放入 Header,并在日志里打印 XID 验证传递链路。第四是数据源代理冲突,Druid 监控 Servlet 和 Sharding-JDBC 跟 Seata 数据源代理冲突导致 SQL 执行异常,需要调整代理顺序让 Seata 代理最外层数据源。第五是异常被 try-catch 吞掉导致事务不回滚,规范要求事务方法内不能吞异常必须抛出,或手动调用 GlobalTransactionContext.rollback()。”

Q29:Seata 1.x 和 2.x 有什么重大变化?

核心要点

  1. Apache 孵化:从 2.0.0 开始捐给 Apache 基金会,groupId 从 io.seata 变为 org.apache.seata,包名部分也调整
  2. TCC 优化:2.0.0 优化 TCC 结构,支持 API 方式访问,新增 seata-integration-tx-api 集成层;1.5.1 引入 TCC Fence 机制
  3. Saga 解耦 Spring:2.1.0 开始 Saga 模块解耦 Spring 依赖,支持非 Spring 环境使用;2.6.0 移除 @LocalTCC 注解
  4. Raft 集群模式:2.1.0 开始内置 Raft 共识支持,2.5+ 生产可用
  5. 控制台增强:集成 Saga 状态机设计器;2.6.0 新增 Console MCP Server 支持(AI Agent 集成)
  6. 多数据源优化:2.6.0 实现多数据源下同源分支事务合并
  7. 配置统一:2.x 统一使用 YAML 配置(application.yml),替代 1.x 的 file.conf + registry.conf
  8. JDK 要求提升:2.6.0 要求 JDK 25+,2.x 早期版本支持 JDK 8/11
  9. 协议优化:2.6.0 优化 Netty 协议,修复 YAML 兼容性问题

面试模板

“Seata 从 1.x 升级到 2.x 是一个较大的版本跨越,最重大的变化是 Seata 捐给了 Apache 孵化器,从 2.0 开始 Maven groupId 从 io.seata 变成了 org.apache.seata,成为 Apache Seata (incubating) 项目。功能层面:TCC 模块做了结构优化,引入了 TCC Fence 篱笆机制自动解决空回滚/悬挂/幂等问题;Saga 模块在 2.1 开始解耦了 Spring 依赖,支持非 Spring 环境,2.6 还移除了 @LocalTCC 注解;从 2.1 版本开始内置了 Raft 共识协议支持 TC 集群无需外部存储,到 2.5 版本生产可用。配置层面,2.x 统一使用 YAML 格式 application.yml,替代了 1.x 分散的 file.conf 和 registry.conf。控制台方面,集成了 Saga 可视化状态机设计器,2.6 版本还新增了 MCP Server 支持 AI Agent 集成。JDK 要求也有提升,2.6 要求 JDK 25+。”

Q30:如果让你设计一个分布式事务框架,你会怎么设计?(开放性设计题)

核心要点:面试考察对分布式事务本质的理解。

  1. 核心抽象:分离协调者(TC)和参与者(RM/TM),TC 无状态化可水平扩展,通过 Raft/DB 同步状态
  2. 多模式支持:AT(无侵入,默认)、TCC(高性能)、Saga(长事务)、XA(强一致),让用户按场景选择
  3. 锁管理:全局锁做成分布式锁服务,支持细粒度(行级)+ 自定义锁策略(分段锁、分桶锁)
  4. 存储层抽象:支持多种存储(DB/Redis/Raft),TC 元数据存储与事务协调逻辑解耦
  5. 高可用:TC 集群 Raft 共识,注册中心服务发现,故障自动转移
  6. 可观测性:XID 全链路追踪、Metrics 指标(QPS/锁/回滚率)、Console 可视化、慢事务告警
  7. 异常容错:自动重试+幂等+超时兜底+人工介入机制
  8. 生态兼容:多语言客户端(不只是 Java)、非 Java 语言通过 gRPC/HTTP 接入;支持多种 RPC 框架和数据库
  9. 性能优化:异步二阶段、批量处理、锁粒度优化、同源分支合并
  10. AI 运维:像 2.6 那样支持 MCP,让 AI Agent 能自动分析异常事务

面试模板

“如果让我设计分布式事务框架,我会从几个核心层面考虑。架构上采用分离的协调者和参与者模型:TC 作为独立部署的协调服务集群,通过 Raft 共识保证高可用和强一致,TM 和 RM 作为客户端 SDK 嵌入业务应用;存储层抽象化,支持 DB、Redis、Raft 多种模式适配不同场景。功能上必须提供多种事务模式覆盖不同场景——无侵入的 AT 模式作为默认首选满足 80% 需求,TCC 模式用于高并发核心链路,Saga 模式用于长事务编排,XA 模式用于强一致需求。性能上,AT 模式的全局锁要支持自定义锁策略,比如分段锁和分桶锁应对热点数据;二阶段提交异步化,支持批量处理和同源分支合并减少网络开销。高可用方面,TC 集群自动故障转移,客户端通过注册中心感知节点变化,重试机制加幂等保证最终一致性。可观测性很重要,提供 XID 全链路日志追踪、Prometheus 指标(QPS/锁等待/回滚率/超时数)、可视化控制台查看事务详情和手工干预能力。生态上要多语言支持,通过 gRPC 协议让 Python、Go 等非 Java 语言也能接入,适配主流 RPC 框架和数据库。运维上支持 AI 集成如 MCP 协议,让 AI Agent 能自动诊断异常事务。”

附录:关键记忆口诀

三大角色:TC 协调、TM 发起、RM 执行
AT 模式:一阶段拦截SQL,前后快照存undo;本地事务直接提,全局锁防脏写
        二阶段提交删日志,回滚用反向SQL,脏写校验不能少
TCC 三阶段:Try 冻结、Confirm 扣减、Cancel 释放
TCC 三宗罪:空回滚(查记录)、悬挂(插标记拒Try)、幂等(状态机)
Saga 特点:长事务、无锁、反向补偿链
XA 缺点:全程持锁,性能低,生产少用
选型口诀:通用业务用AT,核心高并发用TCC,长流程用Saga,强一致低并发才XA
生产红线:集群部署3节点、存储用raft/db禁file、TCC必开Fence、仅顶层加@GlobalTransactional

参考来源

0
博主关闭了所有页面的评论