基于本文回答

播面 播面

文图音视,全方位拆解八股文
0
评论

Seata 的 AT 模式和 TCC 模式有什么区别?

知识点图片

Seata 是一个开源的分布式事务解决方案,提供了四种事务模式:AT、TCC、Saga 和 XA。其中,AT 模式TCC 模式是日常开发中最常用的两种。

它们虽然都属于两阶段提交(2PC)的演进,但核心设计思想、实现机制和适用场景有很大区别。简单来说:AT 模式是框架自动完成的数据库级代理,而 TCC 模式是需要开发者手工编写代码的业务级补偿。

以下是两者的详细区别:


1. 核心机制对比

AT 模式(Automatic Transaction)—— 自动化、无侵入

AT 模式是 Seata 创新的一种非侵入式分布式事务解决方案。它依赖于支持本地 ACID 事务的关系型数据库。

  • 第一阶段(执行并提交): Seata 的 JDBC 代理会拦截业务 SQL,解析 SQL 语义,找到要更新的业务数据,保存数据修改前的状态(before image)和修改后的状态(after image)到 undo_log 表中。然后直接提交本地事务,释放本地数据库锁。
  • 第二阶段(决议):
    • 如果全局提交: 异步清理 undo_log 中的记录,非常轻量快速。
    • 如果全局回滚: 读取 undo_log 中的 before image,生成反向 SQL(例如把 UPDATE 改回原来的值,INSERT 改为 DELETE)并执行,完成数据恢复。

TCC 模式(Try-Confirm-Cancel)—— 手工化、强侵入

TCC 是一种业务层面的两阶段提交,完全不依赖数据库底层的机制,而是需要开发者针对每个操作编写三个方法:

  • 第一阶段 - Try(尝试): 做业务检查(一致性)和资源预留(隔离)。例如:买东西时不直接扣库存,而是把这部分库存“冻结”起来。
  • 第二阶段 - Confirm(确认): 确认执行业务操作。如果 Try 成功,则执行 Confirm,真正扣除冻结的库存。Confirm 操作要求具备幂等性。
  • 第二阶段 - Cancel(取消): 取消执行业务操作。如果全局事务回滚,则执行 Cancel,释放 Try 阶段冻结的库存。Cancel 操作也要求具备幂等性。

2. 多维度差异总结对比表

维度 AT 模式 TCC 模式
业务侵入性 极低。开发者只需写普通 SQL 并加上 @GlobalTransactional 注解,无需改动业务逻辑。 极高。一个接口需要拆分成 Try、Confirm、Cancel 三个方法。
底层依赖 强依赖支持 ACID 的关系型数据库(MySQL、Oracle 等),依赖 Seata 的 SQL 解析器。 无底层依赖。支持关系型数据库、NoSQL(Redis/MongoDB)、甚至是调用第三方 RPC 接口。
锁与隔离性 依赖 Seata 的全局锁机制来保证读写隔离,可能会存在锁竞争导致的性能下降。 无全局锁。隔离性由业务代码自己实现(即 Try 阶段的“资源预留”),锁的粒度更细。
性能 一般。解析 SQL、生成并写入 undo_log、以及全局锁竞争会带来一定的性能损耗。 较高。直接执行业务逻辑,没有 SQL 解析和额外的日志写入,且不需要加全局锁。
开发难度 简单,几乎和单机事务开发体验一致。 困难。需要处理幂等性空回滚防悬挂三大难题。

3. TCC 模式开发必须解决的三大问题

如果选择 TCC 模式,开发者在编写 Confirm 和 Cancel 方法时,必须在代码层面解决以下问题(Seata 新版本提供了一些防悬挂拦截器,但业务逻辑仍需严谨):

  1. 幂等性: 网络超时可能导致 Confirm 或 Cancel 被多次重试调用,代码必须保证执行一次和执行多次的结果是一样的。
  2. 空回滚: 当 Try 阶段因为网络拥堵根本没有执行,或者发生异常失败了,全局事务触发回滚,直接调用了 Cancel。此时 Cancel 方法需要判断出 Try 没有执行过,从而直接返回成功,不能去“释放”根本没冻结的资源。
  3. 防悬挂: 极端的网络情况下,Cancel 比 Try 先执行了。此时 Cancel(空回滚)执行完毕后,Try 请求才到达并执行,这会导致资源被永远冻结(悬挂)。必须记录事务状态,拒绝在 Cancel 执行后到达的 Try 请求。

4. 如何选择?(适用场景)

优先考虑使用 AT 模式:

  • 绝大部分日常的增删改查(CRUD)业务。
  • 项目使用的是主流关系型数据库(如 MySQL)。
  • 要求快速迭代、降低开发成本,团队不想为了事务编写大量的补偿代码。
  • 系统的并发量没有达到极其变态的程度(能容忍一定的性能损耗)。

以下情况必须使用/建议使用 TCC 模式:

  • 核心高并发链路: 例如电商的扣库存、金融系统的扣款,AT 模式的全局锁可能导致数据库行锁竞争严重,TCC 性能更好。
  • 非关系型数据库: 业务数据存储在 Redis、MongoDB 等不支持 SQL 解析的 NoSQL 中。
  • 跨公司/跨系统的接口调用: 比如调用支付宝扣款、调用第三方发短信,这些接口你无法控制它们的数据库,只能通过业务逻辑去调用它们的“退款”或“撤销”接口(Cancel)。
00:00
00:00