Seata
Apache Seata 为跨服务、跨数据源事务提供协调框架。它不能让网络调用天然具备本地数据库事务语义,而是通过事务协调、资源代理、幂等、补偿和状态持久化处理部分失败。
核心角色
| 角色 | 职责 |
|---|---|
| TC(Transaction Coordinator) | 维护全局与分支事务状态,协调提交或回滚 |
| TM(Transaction Manager) | 定义全局事务边界,发起 Begin、Commit 或 Rollback |
| RM(Resource Manager) | 管理分支资源,注册分支并执行提交或回滚 |
模式对比
| 模式 | 一阶段 | 二阶段 | 一致性与隔离 | 适用场景 |
|---|---|---|---|---|
| AT | 本地事务提交业务数据与 Undo Log | 异步清理或按 Undo Log 补偿 | 最终一致;依赖全局锁改善写隔离 | 支持本地事务的关系数据库、低业务侵入 |
| XA | 数据库执行 XA Prepare | XA Commit/Rollback | 一致性与隔离较强;资源锁持有更久 | 数据源支持 XA,能接受阻塞与性能成本 |
| TCC | 业务 Try 预留资源 | Confirm/Cancel | 由业务保证幂等、空回滚和防悬挂 | 高性能、非关系资源或明确资源预留模型 |
| Saga | 各参与者提交本地事务 | 失败后执行补偿 | 最终一致,通常不保证隔离 | 长流程、跨组织或遗留系统 |
“AT 无业务侵入”仅表示不需要手写补偿接口,不代表没有数据库表、DataSource Proxy、SQL 限制、全局锁和运维成本。
AT 模式
一阶段在同一本地事务中完成业务 SQL、Before/After Image 与 undo_log 写入,然后提交本地事务。二阶段提交通常异步删除 Undo Log;回滚时校验数据并生成反向补偿 SQL。
- 每个参与数据库创建符合版本要求的
undo_log表。 - SQL 类型、主键和数据库驱动必须在目标 Seata 版本支持范围内。
- 全局锁只协调加入同一 Seata 全局事务的访问;未接入 Seata 的普通 SQL 仍可能产生并发冲突。
- 回滚校验失败需要监控、告警和人工处理流程。
XA 模式
XA 利用数据库资源自身的 XA Prepare、Commit 和 Rollback。Prepare 后资源通常持续持锁到二阶段结束,隔离更完整,但长事务、TC 故障或网络抖动会放大锁等待。
yaml
seata:
data-source-proxy-mode: XA只有数据库与驱动真实支持 XA 才能使用;“主流数据库支持”不等于所有中间件、连接池和代理组合都经过验证。
TCC 模式
TCC 需要为每个分支实现 Try、Confirm、Cancel:
- Try 检查并预留资源,保存可确认或取消的业务状态。
- Confirm 幂等地把预留转为最终结果。
- Cancel 幂等地释放预留,并处理 Try 未执行时的空回滚。
- 防悬挂保证迟到的 Try 不会在 Cancel 之后再次占用资源。
库存冻结、余额冻结等具有显式预留状态的业务更适合 TCC。
Saga 模式
Saga 把长事务拆成一组本地事务,并为已成功步骤定义补偿操作。补偿不是数据库回滚:外部通知、价格变化、人工审批等副作用可能只能用新的业务动作抵消。
Saga 要明确状态机持久化、重试、超时、补偿失败、人工介入和幂等键。需要严格隔离的短事务通常不应仅因“参与服务较多”就选择 Saga。
Spring 接入
xml
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>yaml
seata:
tx-service-group: order-tx-group
registry:
type: nacos
nacos:
server-addr: ${NACOS_SERVER_ADDR:127.0.0.1:8848}
namespace: ${SEATA_NAMESPACE}
group: SEATA_GROUP
application: seata-server
service:
vgroup-mapping:
order-tx-group: defaultjava
@GlobalTransactional(name = "create-order", rollbackFor = Exception.class)
public void createOrder(CreateOrderCommand command) {
// 调用参与同一全局事务的分支服务
}配置键和接入方式会随版本变化,不能继续复制 Seata 1.4.2 的 Starter 排除写法覆盖 BOM。
事务边界
- 不把远程事务无限扩大;接口调用越多、耗时越长,失败概率和锁成本越高。
- 设置全局与分支超时,并确保 RPC 超时、重试次数和事务超时协调。
- RPC 自动重试必须有业务幂等键,不能只依赖数据库唯一键处理全部副作用。
- MQ、缓存、搜索索引等异构资源通常更适合 Outbox、事务消息或 Saga,不应强行塞入数据库 AT。
- 监控全局/分支事务数、回滚、超时、重试、Undo Log、Session Store 和 TC 可用性。