复制代码
Seata(Simple Extensible Autonomous Transaction Architecture) 是阿里开源的一站式分布式事务解决方案,以**高性能、易用性、轻量**为核心,解决微服务下**跨服务、跨库**的数据一致性问题,保证:**要么全部成功,要么全部回滚**。这里是它的官方网站:[seata官方链接](https://seata.apache.org/zh-cn/blog/)
在微服务场景中,一个业务操作可能需要调用多个独立服务,每个服务都有自己的数据库。如何保证这些跨服务、跨数据库的数据操作要么全部成功,要么全部失败(即满足 ACID 中的"原子性"),就是分布式事务要解决的核心问题。而Seata 提供了这样的能力。
一、Seata中的三大核心角色
复制代码
在 Seata 中定义了三个核心的角色,而 Seata 事务由这三个角色协同完成。分别是 TC(Transaction Coordinator)事务协调器、TM(Transaction Manager)事务管理器和 RM(Resource Manager)资源管理器。
**1)TC 事务协调器**
特点: 事务的"大脑"和"总指挥"。它负责维护全局事务和分支事务的状态,驱动全局事务的提交或回滚。它是一个独立的 Seata-Server 进程。
**2)TM 事务管理器**
特点:事务的"发起者"。它定义全局事务的边界,负责开启、提交或回滚一个全局事务。一般通过 @GlobalTransactional 注解集成在业务微服务应用中。
**3)RM 资源管理器**
特点:事务的"执行者"。它管理分支事务,负责向 TC 注册分支事务、报告分支事务状态,并驱动分支事务的提交和回滚。这里管理的"资源"通常指数据库。一般通过数据源代理集成在业务微服务应用中。
**4)三者的协作关系**
TM 向 TC 发起"开启全局事务",生成全局唯一的 XID。这个 XID 会在整个微服务调用链中传递。每个被调用的服务(其 RM)会向 TC 注册自己的分支事务。最终,由 TM 决定向 TC 发起全局提交或回滚,TC 再调度所有相关的 RM 完成各自分支事务的提交或回滚。
这种协作关系也就是下文要介绍的 Seata 的四种关系模式的 AT 模式。
二、Seata中的四大事务
复制代码
说完了 Seata 的三个基本工作角色,接下来就谈谈 Seata 中最核心的亮点,Seata 的四种事务模式,它们分别是 AT模式(默认)、TCC模式、Saga模式、XA模式,Seata 中这么多的模式是为了适应不同的业务场景,在性能、一致性、侵入性之间做出权衡。下面来详细介绍一下这四种模式。
**1)AT模式**
这种模式是默认、最主流的、无侵入的模式,它属于自动补偿型。基于支持本地 ACID 事务的关系型数据库(如 MySQL)。
特点: 一阶段: 在执行业务 SQL 的同时,自动拦截并生成数据快照(前置镜像)和回滚日志(后置镜像),直接提交本地事务。二阶段:提交: 异步删除回滚日志,非常快。回滚: 根据回滚日志,自动生成反向补偿 SQL 进行回滚。
优点:对代码零侵入(仅加一个注解)、高性能、业务开发简单。
工作流程
**2)TCC模式**
这种模式是高性能、手动编码的模式,它属于手动补偿型。需要业务代码实现 Try、Confirm、Cancel 三个接口。
特点:一阶段 (Try): 调用自定义的 Try 方法,预留业务资源(如冻结金额、占库存)。二阶段:提交 (Confirm): 调用自定义的 Confirm 方法,确认执行,基于 Try 预留的资源完成最终操作。 回滚 (Cancel): 调用自定义的 Cancel 方法,释放预留的资源。
优点:无锁、高性能、可应用于非关系型数据库。
**3)Saga模式**
这种模式是长事务、最终一致的模式,它属于长事务解决方案类型,通过状态机编排一系列服务调用。每个服务参与者都实现业务逻辑和一个对应的补偿回滚逻辑。
特点:事务正常执行时,顺序执行各参与者。当某个参与者失败时,逆向依次调用之前所有已执行参与者的补偿逻辑。
优点:一阶段就提交本地事务,无锁,高性能,吞吐高。适合长时间的业务流程。
**4)XA模式**
这种模式是强一致、标准协议的模式,它属于传统标准类型,利用数据库本身提供的 XA 协议实现。(XA协议:就是数据库层面的 2PC(两阶段提交)标准规范,由 X/Open 组织制定,用来保证跨多个数据库 / 资源管理器的事务 要么全部提交,要么全部回滚,实现强一致性。简单说XA 就是让多个数据库一起 "同时成功、同时失败" 的官方标准协议。)
特点:一阶段: TM 通知所有 RM 准备(Prepare)事务,RM 执行 SQL 但不提交。二阶段: TM 根据所有 RM 的 Prepare 结果,通知所有 RM 统一提交(Commit)或回滚(Rollback)。
优点:强一致性,是分布式事务的工业标准,对业务无侵入。
三、四种事务的工作流程
复制代码
AT 模式是 Seata 的"招牌",其核心是两阶段提交的自动化版本,在第一阶段就提交本地事务,利用回滚日志实现第二阶段可能的回滚。
参与的角色:TM: 发起全局事务。TC: 记录全局事务和分支事务状态,驱动二阶段。RM (已代理的数据源): 执行业务 SQL,自动生成/使用回滚日志。
核心数据结构 - 回滚日志 undo_log表:每个业务库中都需要创建此表,用于存储数据修改前后的镜像(快照),是实现自动回滚的基石。
sql
复制代码
CREATE TABLE `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 '回滚信息(数据快照)',
`log_status` INT NOT NULL COMMENT '状态',
`log_created` DATETIME NOT NULL COMMENT '创建时间',
`log_modified` DATETIME NOT NULL COMMENT '修改时间',
PRIMARY KEY (`branch_id`),
KEY `idx_xid` (`xid`)
);
复制代码
**具体工作流程:**
**第一阶段:执行与提交本地事务**
1)TM 开启全局事务: TM 向 TC 注册一个全局事务,TC 生成全局唯一的 XID。
2)业务执行与拦截: RM 执行业务 SQL 时,被 Seata 的 DataSourceProxy 代理拦截。
3)生成前后镜像:
前置镜像 (Before Image): 根据 SQL 的 WHERE 条件,查询出数据修改前的状态,并保存。
执行 SQL: 执行业务 SQL 更新数据。
后置镜像 (After Image): 根据 SQL 的主键,查询出数据修改后的状态,并保存。
4)注册分支与插入回滚日志: RM 将前后镜像、表名、主键等信息序列化,作为回滚日志(rollback_info),连同业务 SQL 的结果,在同一个本地数据库事务中,写入 undo_log表,并向 TC 注册分支事务。注意:此时业务数据的修改和回滚日志的写入是原子的。
5)提交本地事务: 立即提交本地数据库事务,释放本地锁。此时,业务数据的更改对其它本地事务已可见。
**第二阶段:由 TC 统一协调提交或回滚**
1.场景一:全局提交
1)TM 成功完成所有业务,向 TC 发起全局提交请求。
2)TC 迅速(异步)地向所有相关 RM 发出"删除对应 XID 和分支 ID 的回滚日志"的请求。
3)RM 收到请求后,删除 undo_log中对应的日志行。整个过程非常快,因为不需要处理业务数据。
2.场景二:全局回滚
1)TM 在业务链中捕获到异常,向 TC 发起全局回滚请求。
2)TC 根据 XID 找到所有已注册的分支事务,向各 RM 发出回滚请求。
3)RM 收到请求后:
a. 查询本地 undo_log表,获取到完整的数据回滚日志。
b. 数据校验: 比较当前数据库中的数据(Current Image)与后置镜像(After Image)。如果一致,说明数据自一阶段后未被其他本地事务修改,可以安全回滚。如果不一致(出现了"脏写"),则需要根据配置的策略(如重试、报警)处理。
c. 执行反向补偿: 根据回滚日志中的前置镜像(Before Image),自动生成一条反向的 UPDATE 语句,将数据恢复原状,并删除本地的回滚日志。
4)RM 向 TC 报告回滚结果。
2.TCC 模式的工作流程
复制代码
TCC 模式是两阶段提交的手动实现版本,需要业务代码显式定义三个阶段的操作。它将资源层面的操作(如数据库行锁)提升到了业务层面(如状态标记)。
核心阶段:
1)Try: 尝试执行,完成所有业务检查,并预留必要的业务资源。核心是"预留",状态为"中间态",例如:将账户金额冻结,库存状态标记为占用。
2)Confirm: 确认执行,使用 Try 阶段预留的资源执行业务。Confirm 操作必须保证幂等性。核心是"确认",状态为"最终态",例如:将冻结的金额真正扣减,将占用的库存标记为已出库。
3)Cancel: 取消执行,释放 Try 阶段预留的业务资源。Cancel 操作也必须保证幂等性。核心是"释放",例如:解冻金额,释放占用的库存。
**具体工作流程:**
**第一阶段:执行所有参与者的 Try 方法**
1)TM 开启全局事务。
2)按业务顺序调用各个服务的 Try 接口。
3)每个服务的 Try 接口执行本地事务,完成业务检查,并将资源置于"预留/中间态",提交本地事务。
4)所有 Try 接口执行成功,第一阶段结束。
**第二阶段:由 TC 统一协调执行 Confirm 或 Cancel**
1.场景一:全局提交 (Confirm)
1)TM 向 TC 发起全局 Confirm 请求。
2)TC 按正向顺序(与 Try 调用顺序相同)调用所有参与者的 Confirm 接口。
3)各参与者的 Confirm 接口使用 Try 阶段预留的资源,完成业务逻辑的最终确认,提交本地事务。
2.场景二:全局回滚 (Cancel)
1)TM 向 TC 发起全局 Cancel 请求。
2)TC 按逆向顺序(与 Try 调用顺序相反)调用所有已成功执行 Try 的参与者的 Cancel 接口。
3)各参与者的 Cancel 接口释放 Try 阶段预留的资源,提交本地事务。
3.Saga 模式的工作流程
复制代码
Saga 是一种最终一致性的长事务解决方案,其核心思想是将一个长事务拆分为多个本地短事务,每个短事务都有一个对应的补偿操作。事务正向执行,失败时则逆向执行补偿。
执行方式:
1)编排式 (Choreography): 由参与者通过事件/消息自主驱动流程,Seata 的 Saga 状态机属于此类。
2)协同式 (Orchestration): 由一个中心协调器来驱动,Seata 的 Saga 模式主要指这种,由 TC 作为协调器。
**具体工作流程:**
1)事务启动: TM 向 TC 发起 Saga 事务开始,TC 根据预定义的状态机(描述服务调用和补偿的顺序与条件)开始执行。
2)正向执行阶段: TC 按状态机定义,顺序调用各个服务的业务逻辑(对应 TCC 的 Try,但这里直接提交)。
3)本地事务提交: 每个服务执行自己的业务逻辑,立即提交本地事务。因此无锁,性能好,但数据立即可见(无隔离性)。
4)决策与补偿:
如果所有服务调用成功,Saga 事务完成。
如果某个服务调用失败(业务失败或超时):
a. TC 启动补偿流程。
b. TC 按照与执行相反的顺序,依次调用之前所有已成功执行过的服务的补偿方法。
c. 每个补偿方法执行自己的回滚逻辑,并提交本地事务。
5)结束: 补偿流程执行完毕,事务结束,系统达到最终一致状态。
4. 模式的工作流程
复制代码
XA 是分布式事务的传统标准,由数据库厂商提供支持。它也是两阶段提交协议。
**具体工作流程:**
**第一阶段:准备阶段**
1)TM 开启全局事务。
2)TM 通知所有参与其中的 RM(数据库)执行 SQL,但不提交。
3)每个 RM 执行 SQL,将事务置于"准备就绪"状态,并将可以提交(Ready)或需要回滚的信息反馈 给 TM。此时,数据已被锁定。
**第二阶段:提交/回滚阶段**
1.场景一:全局提交
1)TM 收到所有 RM 的"准备成功"响应。
2)TM 向所有 RM 发送 commit 指令。
3)所有 RM 收到指令后,正式提交各自的事务,释放锁。
2.场景二:全局回滚
1)TM 收到任意一个 RM 的"准备失败"响应或超时。
2)TM 向所有 RM 发送 rollback 指令。
3)所有 RM 收到指令后,回滚各自处于准备状态的事务,释放锁。
以上主要介绍了 Seata 的核心工作模式及其流程,并不是很详细,仅供参考。