分布式事务方案对比

先明确一个核心前提

分布式事务要解决的是:一个业务操作跨了多个数据库或服务,如何保证数据一致性?

解决方案分为两大阵营:

  • 刚性事务(强一致性):Seata 的 AT、TCC、XA 模式。追求数据实时一致,所有服务要么一起成功,要么一起失败。

  • 柔性事务(最终一致性):本地消息表、MQ 事务消息。允许短暂不一致,通过重试保证数据最终一定对齐。

本地消息表

核心思想 :在本地业务数据库里建一张 outbox 表,把"写业务数据"和"写待发送消息"放在同一个本地事务里。业务成功后,用一个定时任务去扫 outbox 表,把消息发给 MQ,发送成功后再删除或标记这条消息。

特点

  • 优点:实现简单,不依赖特殊 MQ,和业务代码耦合低。

  • 缺点:需要自己写定时任务和异常处理;消息可能重复发送,消费者必须幂等;有延迟,定时任务扫描间隔决定了消息的延迟时间。

适用场景:公司没有 RocketMQ 这类支持事务消息的 MQ,只能用 RabbitMQ 或 Kafka,但又需要保证消息一定发出去。

MQ 事务消息

核心思想:利用 RocketMQ 原生的事务消息机制,把"发送消息"和"执行本地事务"绑定在一起。先发半消息(消费者不可见),再执行本地事务,根据本地事务结果决定半消息是提交(消费者可见)还是回滚(丢弃)。

特点

  • 优点:消息延迟低(实时性远高于本地消息表),不需要自己写定时任务和 outbox 表,RocketMQ 自带回查机制保证最终一致性。

  • 缺点:必须用 RocketMQ(RabbitMQ 和 Kafka 原生不支持);消费者必须幂等。

适用场景:公司有 RocketMQ,且对数据一致性的实时性要求高------比如下单后要立刻扣库存,不能等几秒后才发消息。

Seata AT 模式

核心思想:Seata 介入你的 SQL 执行过程,在事务提交前自动记录回滚日志(undo_log 表)。如果需要回滚,Seata 根据 undo_log 自动生成反向 SQL,把数据恢复原状。你的代码不需要写任何回滚逻辑。

特点

  • 优点 :对业务代码零侵入(只需一个 @GlobalTransactional 注解),自动生成回滚日志,自动回滚。

  • 缺点 :依赖 Seata Server(需要额外部署);性能损耗比本地事务高;不支持 Redis、MongoDB 等非关系型数据库;不支持 SELECT ... FOR UPDATE 这类显式加锁的 SQL。

适用场景:Java 微服务项目,数据库全部是 MySQL(或其他关系型数据库),不想侵入业务代码,想用注解自动管理分布式事务。

Seata TCC 模式

核心思想:TCC 把每个服务需要做的事情拆成三步:Try(锁定资源)、Confirm(正式执行)、Cancel(释放资源)。所有 Try 都成功后,统一 Confirm;任何一个 Try 失败,统一 Cancel。这是业务层面的补偿,不是数据库层面的回滚。

特点

  • 优点:性能更高(没有全局行锁),支持非数据库资源(Redis、文件系统等),业务可控性强。

  • 缺点:代码侵入性极高,每个接口都需要实现 Try、Confirm、Cancel 三个方法;开发工作量大,容易出错。

适用场景:对性能要求极高的场景(比如秒杀扣库存),或者涉及非数据库资源(需要同时操作 Redis 和 MySQL),或者公司已经有 TCC 框架沉淀。

Seata XA 模式

核心思想:利用数据库自身的 XA 协议(两阶段提交)。Seata 不在 SQL 层面做拦截,而是把分布式事务完全交给数据库去管理。第一阶段各数据库执行 SQL 但不提交(Prepare),第二阶段 Seata 通知所有数据库统一提交或回滚(Commit/Rollback)。

特点

  • 优点:对业务代码几乎零侵入;强一致性,数据绝不脏读。

  • 缺点:性能最差(全局锁持有时间长,并发吞吐量断崖式下降);依赖数据库支持 XA 协议(MySQL 5.7+ 支持);不支持 Redis 等非数据库资源。

适用场景:对数据一致性要求极高(比如金融、会计系统),但对性能要求不高,且所有资源都是支持 XA 协议的关系型数据库。在实际生产中很少使用,因为性能代价太大。

Seata Saga 模式

核心思想是把一个长事务拆成多个短事务,每个短事务都有自己的补偿操作。如果某个步骤失败,不再回滚已经成功的步骤,而是按顺序反向执行补偿操作。

优点 是不依赖全局锁和 undo_log,适合长事务(如需要人工审核的订单流程);缺点是必须为每个正向操作编写反向补偿逻辑。

这种方式适用场景是业务流程长、需要人工干预或调用外部系统(如银行接口)。

总结

没有银弹。刚性事务(AT、TCC、XA)追求强一致性,但各有代价;柔性事务(本地消息表、MQ 事务消息)允许短暂不一致,但通过重试保证最终对齐。架构设计的本质是权衡------你在选择方案的同时,也是在选择你愿意为数据一致性付出多大的性能代价。

相关推荐
starzy19901 天前
SparkSQL 数据源与底层架构深度剖析
大数据·分布式·架构·spark
番茄炒鸡蛋加糖1 天前
RabbitMQ 全套复盘 + Nacos+ES+MyBatis-Plus 梳理
分布式·rabbitmq
零域码客2 天前
从 SQLite 到 PostgreSQL:轻量单机到分布式架构选型、避坑与迁移全解析
分布式·postgresql·sqlite·wal·架构设计·后端开发·数据库选型
ltl2 天前
2PC 的真实失败模式:阻塞、脑裂与恢复
分布式
霸道流氓气质2 天前
分布式系统设计:技术解析与实践
分布式
画中有画2 天前
分布式锁架构方案选型与实践
分布式·架构
ACP广源盛139246256732 天前
蚂蚁百灵 Ling‑3.0‑flash 开源 + 昇腾 0‑Day 原生适配@ACP#GSV9001E 在国产算力矩阵中的机会与落地场景
大数据·人工智能·分布式·单片机·嵌入式硬件
汽车仪器仪表相关领域3 天前
KRYPTON坚固型IP67 EtherCAT总线数据采集模块:工业级分布式采集方案
分布式·功能测试·汽车·压力测试·可用性测试
霸道流氓气质3 天前
Java中信号量(Semaphore):从本地到分布式
java·开发语言·分布式
naierfengdian3 天前
分布式风电助力乡村能源转型的技术路径
分布式·能源