事务中间件:分布式事务与 Seata
分布式事务就是跨多个数据库/服务的事务,要么全成功要么全回滚。你下单要扣库存(库存服务)、减余额(账户服务)、写订单(订单服务),三个服务三个数据库,怎么保证三步要么全成要么全撤?这就是事务中间件要解决的问题。
6.1 CAP 定理与 BASE 理论
论分布式系统的不可能三角
CAP 定理:一致性(Consistency)、可用性(Availability)、分区容错(Partition tolerance),三者只能取二。网络分区一定会发生(网线拔了),所以 P 必须保,实际只能在 C 和 A 之间选:CP(ZooKeeper,分区时拒绝服务保一致)或 AP(Eureka/Nacos,分区时还能服务但数据可能不一致)。
BASE 理论:基本可用(Basically Available)、软状态(Soft State)、最终一致(Eventually Consistent)。这是 CAP 的 AP 路线——牺牲强一致性,保证最终一致。绝大多数互联网系统走 BASE。
6.2 2PC:两阶段提交
2PC(Two-Phase Commit)是最经典的分布式事务协议。有一个协调者和多个参与者:
① 同步阻塞:参与者等协调者指令时一直阻塞,资源不能干别的。② 单点故障:协调者挂了,参与者永远卡住。③ 数据不一致:Commit 阶段部分参与者收到、部分没收到(网络问题),数据就不一致了。
6.3 3PC:三阶段提交
3PC 在 2PC 基础上加了一个 CanCommit 阶段和超时机制,减少阻塞。但还是有数据不一致问题,而且更复杂。实际生产很少用 3PC,了解概念就行。
6.4 TCC:业务层两阶段
论TCC 的思路
TCC = Try-Confirm-Cancel,业务层面的两阶段。不是数据库层的锁,而是你自己写三个接口:
Try:预留资源(比如冻结库存、冻结余额,不真正扣减)。
Confirm:所有 Try 都成功了,正式执行(扣库存、减余额)。
Cancel:有 Try 失败了,回滚(解冻库存、解冻余额)。
三个经典问题:① 空回滚:Try 没到但 Cancel 到了,要处理;② 幂等:Confirm/Cancel 可能重复调用,要幂等;③ 悬挂:Cancel 先到 Try 后到,Try 不能执行。
6.5 Seata:阿里开源分布式事务框架
Seata 是现在国内最流行的分布式事务框架。它有三个角色:TC(Transaction Coordinator,事务协调者,独立部署)、TM(Transaction Manager,定义全局事务)、RM(Resource Manager,管分支事务)。支持四种模式:
| 模式 | 原理 | 适合 |
|---|---|---|
| AT | 自动补偿。一阶段直接提交本地事务,记录 undo log;二阶段根据全局结果决定提交或回滚(自动生成反向 SQL) | 大多数业务,无侵入,最常用 |
| TCC | 手写 Try/Confirm/Cancel 三个接口 | 高要求、性能好 |
| Saga | 长事务,正向流程 + 逆向补偿 | 跨多服务长流程 |
| XA | 数据库层面 2PC,强一致 | 传统数据库强一致场景 |
Seata AT 模式使用(Spring Boot 注解式)
6.6 Saga 与本地消息表
Saga 模式:把长事务拆成一系列本地事务,每个本地事务配一个补偿操作。正向执行:T1→T2→T3,任一步失败就逆向补偿:C3→C2→C1。适合流程长、参与方多的场景。
本地消息表:最朴素的最终一致性方案。业务操作和消息存在同一个本地事务里(要么都成要么都不成),然后定时任务把消息发到 MQ,下游消费。RocketMQ 的事务消息就是这个思路。
| 方案 | 一致性 | 性能 | 复杂度 | 适合场景 |
|---|---|---|---|---|
| 2PC/XA | 强一致 | 差(同步阻塞) | 中 | 传统数据库强一致 |
| TCC | 最终一致 | 好 | 高(手写三接口) | 金融、资金类 |
| Seata AT | 最终一致 | 好 | 低(注解式) | 大多数业务,推荐 |
| Saga | 最终一致 | 好 | 中 | 长流程跨服务 |
| 本地消息表 | 最终一致 | 好 | 低 | 异步解耦、日志类 |
Q1:CAP 定理实际怎么选?
查看答案
网络分区一定会发生,P 必须保。CP 选 ZooKeeper(强一致但分区时不可用),AP 选 Eureka/Nacos(高可用但可能短暂不一致)。互联网系统大多选 AP + 最终一致。
Q2:2PC 为什么有数据不一致?
查看答案
Commit 阶段协调者发 Commit 给所有参与者,如果网络问题部分收到部分没收到,收到的提交了、没收到的还锁着,数据就不一致了。
Q3:Seata AT 模式原理?
查看答案
一阶段直接提交本地事务(不锁),同时记录 undo log 和全局锁。二阶段:全局成功就删 undo log;全局失败就用 undo log 生成反向 SQL 回滚。无业务侵入,注解式。
① CAP 三选二,实际都保 P,互联网系统选 AP + 最终一致(BASE)。
② 2PC 有同步阻塞/单点/不一致三大硬伤;TCC 手写三接口但性能好;Seata AT 无侵入最常用。
③ 大多数业务用 Seata AT 或本地消息表就够了,别为了强一致上 XA。