一、Seata 是什么
Seata 是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务
二、Seata 能做什么
Seata 致力于提供 高性能 和 简单易用的 分布式事务服务。seata 将为用户提供 AT、TCC、SAGA、XA 事务模式,为用户打造一站式的分布式解决方案。
三、Seata 术语
TC-事务协调者: 维护全局和分支事务的状态,驱动全局事务提交或回滚。
TM-事务管理器: 定义全局事务的范围:开始全局事务、提交或回滚全局事务。
RM-资源管理器: 管理分支事务处理的资源,与TC 交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
四、执行流程
- TM 向 TC开启一个全局事务,全局事务创建成功并生成一个全局唯一的XID
- XID 在微服务调用链的上下文中传播
- RM 向 TC 注册分支事务,将其纳入 XID 对应全局事务的关系
- TM 向 TC 发起针对 XID 的全局提交或回滚决议
- TC 调度 XID 下管辖的全部分支事务完成提交或回滚请求
五、举个栗子
-
TM 告知 TC 开启一个全局事务
子业务向 TC 注册一个分支事务 -
第一个子服务执行完后
TM 让第二个子业务向TC 注册一个子服务 -
第二个子服务执行完之后
TM 安排第三个子业务向TC 注册一个分支事务 -
第三个子服务执行完之后
TM 告诉TC 全局事务执行完毕 -
三个子业务和主业务,但凡有一个执行失败,TC 就能知道,并且让此间所有事务回滚解锁。
六、使用 Seata
- 只需要使用@GlobalTransactional 标注在业务方法上就行
- 创建UNDO_LOG回滚日志表
- 没提交的事务可以回滚
- 已提交的事务要做反向补偿
- ====> 这里涉及到事务状态:已提交和未提交
- 事务的状态通常包括以下几种:已提交、未提交、已回滚和进行中。已提交的事务是指已经成功执行并将结果永久保存到数据库中的事务。未提交的事务是指已经开始但尚未完成的事务。已回滚的事务是指由于某种原因被撤销或者回滚的事务。进行中的事务是指正在执行但尚未完成的事务。这些状态是数据库事务处理中常见的状态。
七、Seata 控制分布式事务
- 每一个微服务都创建 undo_log 表
- 安装事务协调器,下载安装seata 服务器软件包
- 整合 seata
a. 导入seata依赖
b. 解压并启动 seata-server
ⅰ. 修改 registry.conf 文件- 使用 nacos 作为注册中心
ⅱ. 修改file.conf 中(seata 配置文件) - 配置事务日志存放
c. 标注@GlobalTransactional 在主业务方法上
d. 所有想要用到分布式事务的微服务,都需要使用 seata DataSourceProxy 代理自己的数据源
ⅰ. 添加配置类 - 配置代理数据源
a. DataSourceProperty 使用 DataSourceProxy 包装
e. 每个微服务,都必须导入 registry.conf 和 file.conf 文件
ⅰ. file.conf 的 sevice.vgroup_mapping 配置必须和 spring.application.name 一致
f. 测试启动分布式事务
g. 给分布式大事务的入口标注 @GlobalTransactional
h. 每一个远程的小事务用@Transactional ·
- 使用 nacos 作为注册中心
八、AT 模式
基于二阶提交模型的演变
使用场景:不适用与高并发场景,适用于后台管理系统(不要求高并发)
高并发不去考虑2pc和tcc模式
而考虑基于消息服务的最大努力和可靠消息
九、Seata 原理
一阶段加载
在一阶段,Seata 会拦截 “业务 SQL”
- 解析 SQL 语义,找到“业务 SQL”要更新的业务数据,在业务数据被更新前,将其保存成 “before image”
- 执行 “业务SQL” 更新业务数据,在业务数据被更新之后,
- 将其保存成 “after image”,最后生成行锁
以上操作全部在一个数据库事务内完成,这样保证了一阶段操作的原子性。
二阶段提交
- 如果顺利提交的话,因为 “业务 SQL” 在一阶段已经提交到数据库,所以 Seata 框架只需将一阶段保存的快照数据和行锁删掉,完成数据清理即可
二阶段回滚
- 如果异常的话,回滚通过一阶段的回滚日志进行反向补偿。Seata 需要回滚一阶段已经执行的“业务SQL”,还原数据。
回滚方式便是用 “before image” 还原业务数据,但在还原前要首先校验脏写,对比“数据库当前业务数据” 和 “after image”,如果两份数据完全一致就说明没有脏写,可以还原业务数据,如果不一致就说明有脏写,出现脏写就需要转人工处理。
声明:摘抄整理自周阳老师的视频,作为个人学习笔记
十、拓展的知识
- 一旦涉及到跨库的更新操作,分布式事务往往会使问题变得复杂。分表虽然无法缓解数据库压力,但却能够提供尽量将分布式事务转化为本地事务的可能。(来源 apache shardingSphere)
- Seata提供了分布式事务的管理和协调功能,可以帮助将分布式事务转化为本地事务,保证操作的原子性。
从以上两点可知,可以结合 Seata 和 分表,实现将分布式事务转化为本地事务,确保事务的一致性和可靠性。
举个例子,假设有一个电子商务系统,其中涉及订单服务和库存服务两个微服务。当用户下单时,需要同时扣减库存并生成订单,这涉及到跨多个服务的操作,即一个分布式事务。为了将这个分布式事务转化为本地事务,可以引入一个事务协调器(如Seata),在订单服务和库存服务之间协调事务的提交或回滚。通过事务协调器的支持,可以将原本的跨服务事务转化为本地事务,确保订单生成和库存扣减的一致性和可靠性。
通过分表,可以将订单表和库存表分开管理,使得订单服务和库存服务可以独立操作各自的表,从而简化了跨服务的事务处理。这样,即使涉及分布式事务,分表也有助于将复杂的跨表操作转化为本地事务操作,提高系统的性能和可维护性。