当前位置: 首页 > news >正文

Seata学习(三):Seata AT模式练习

一、AT模式流程分析

1、概念

     AT 模式是 Seata 创新的一种非侵入式的分布式事务解决方案,Seata 在内部做了对数据库

    操作的代理层,我们使用 Seata AT 模式时,seata 会创建数据源DataSource的代理对象

    DataSourceProxy,实际上用的是 Seata 自带的数据源代理DataSourceProxy,Seata 在

    这层代理中加入了很多逻辑,比如插入回滚 undo_log 日志,检查全局锁等。

    在 AT 模式下,用户只需关注自己的“业务 SQL”,用户的 “业务 SQL” 作为一阶段,

    Seata 框架会自动生成事务的二阶段提交和回滚操作。

2、AT模式执行流程

     AT 模式事务提交主要分为两阶段,分别是:

     1)一阶段:

           在一阶段中,Seata会拦截“业务SQL“,首先解析SQL语义,找到要更新的业务数据,

           在数据被更新前,保存下来"undo(undo log,即原数据,更改之前的数据)",然后执

           行”业务SQL“更新数据,更新之后再次保存数据”redo(redo log,即更改之后的数据)“,

           最后生成行锁(保证库中数据的一致性,保证当前数据不会被其他线程操作),这些操作

           都在本地数据库事务内完成,这样保证了一阶段的原子性。

          业务SQL和undo log日志记录在同一个本地事务中提交,最后释放本地锁和连接资源。

     2)二阶段:

          相对一阶段,二阶段比较简单,二阶段主要做2件事情,即:

                (1)提交异步化(提交全局事务),非常快速地完成

                (2)回滚,通过一阶段的回滚日志进行反向补偿

          如果之前的一阶段中有本地事务没有通过,那么就执行全局回滚,否在执行全局提交,

          回滚用到的就是一阶段记录的"undo Log",通过回滚记录生成反向更新SQL并执行,

          已完成分支的回滚。全局事务“提交/回滚”完成后会释放所有资源和删除所有日志。

      AT模式流程如下图所示:

           

二、AT模式使用练习

       以订单服务order 和 仓库服务stock 为例,来学习下 AT 模式的使用;

       大致业务流程如下:订单服务通过OpenFegin远程调用库存服务,然后stock库存服务减

       库存,order订单服务生成订单;

       表结构设计:

       1)订单表

               

              

       2)仓库表

             

        3)在 order 和 stock服务都要创建undo_log表,建表语句如下:

CREATE TABLE `undo_log` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`branch_id` bigint(20) NOT NULL,`xid` varchar(100) NOT NULL,`context` varchar(128) NOT NULL,`rollback_info` longblob NOT NULL,`log_status` int(11) NOT NULL,`log_created` datetime NOT NULL,`log_modified` datetime NOT NULL,`ext` varchar(100) DEFAULT NULL,PRIMARY KEY (`id`),UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

1、引入依赖

<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId><exclusions><exclusion><groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId></exclusion></exclusions></dependency><dependency><groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId></dependency>

2、配置seata 

     在当前服务的配置文件中配置seata相关配置,(order与stock 配置完全一致);

     配置内容如下:

          

#配置Seata
#注意:seata server、server Client 共用一个配置,即seataServer.properties
seata:#用于唯一标识一个 Seata Client(即一个微服务实例),通常与 spring.application.name 或服务注册名称一致application-id: seata-at-orderregistry:type: nacosnacos:server-addr: localhost:8848#注意:seata server 与 seata client 的 namespace、group 必须一致namespace: ""#seata server 所在的分组,默认是 SEATA_GROUPgroup: SEATA_GROUP#seata server 服务名称,若seata server没有修改,则可以不配置application: seata-servercluster: defaultusername: nacospassword: nacosconfig:type: nacosnacos:server-addr: 47.117.80.49:8848namespace: ""#在1.4之后新增的配置dataId: seataServer.properties#seata server 所在的分组,默认是 SEATA_GROUPgroup: SEATA_GROUP下边2个可以不配置username: nacospassword: nacos#配置当前分支事务的事务分组#事务组名称,seataServer.properties 中配置的 service.vgroupMapping.事务分组名称(如:service.vgroupMapping.my_group)一致,tx-service-group: my_group# 与TC 通信的配置service:# 将当前分支事务(TM/RM)的分组映射到TCC(即seata server)中的集群上(即registry.config 文件中注册中心的配置项的 cluster = "default"),#这样即使分支事务的分组不同也可参与同一个全局事务vgroup-mapping:my_group: default #key=事务分组名称,需要与 seataServer.properties中配置的 “ service.vgroupMapping.事务分组名称 ”的值,值是seata server中配置的集群名称,如:service.vgroupMapping.my_group=default

3、示例代码

     AT模式使用时,只需要在order 服务中添加注解 @GlobalTransactional 来开启全局事务就

    行了,其他不用修改现有逻辑。@GlobalTransactional 可以标注在 order服务的controller层

    或service层,没什么区别。

    示例代码如下:

@RestController
public class OrderController {@Autowiredprivate OrderService orderService;@GetMapping("/order/create")/*** Order 相当于TM,即主动开启分布式全局事务的角色;* Stock 相当于 RM** 问题:开启全局分布式事务后,本地服务为什么不需要开启本地事务了?*     seata 中通过数据源代理 来执行业务逻辑,然后seata 会自动帮我们提交本地事务;*     即本地事务由seata来提交,而不是以前的由spring显示的提交*/@GlobalTransactional(timeoutMills = 120000)// 开启分布式事务public String create(){try {orderService.create();}catch (Exception e){/*** 将异常抛出去**///throw new RuntimeException("生成订单成功失败");}return "生成订单成功";}
}

注意:

     在AT 模式中,若 RM 角色的服务(如:stock)使用@ControllerAdvice 处理了全局

    异常(RM的异常没有抛出),这就导致在这个分布式事务的流程中RM 的角色的异常不

    能被seata识别,认为分支事务执行通过,全局事务正常提交,这就会造成 RM(如 stock)

    角色本地事务回滚了,而 RM(如:order) 角色事务提交了,库中数据异常的情况。

http://www.dtcms.com/a/330990.html

相关文章:

  • CMake语法与Bash语法的区别
  • 解剖HashMap的put <三> JDK1.8
  • 会议系统进程池管理:初始化、通信与状态同步详解
  • 从 Notion 的水土不服到 Codes 的本土突围:研发管理工具的适性之道​
  • Apache 虚拟主机配置冲突导致 404 错误的排查总结
  • [机器学习]08-基于逻辑回归模型的鸢尾花数据集分类
  • AXI GPIO 2——ZYNQ学习笔记
  • 力扣top100(day03-02)--图论
  • Java 技术栈中间件优雅停机方案设计与实现全景图
  • 【JavaEE】多线程 -- 线程状态
  • 数据结构之顺序表相关算法题
  • 【数据分享】351个地级市农业相关数据(2013-2022)-有缺失值
  • linux中date命令
  • SAP-ABAP:SAP消息系统深度解析:架构设计与企业级应用实践
  • Wireshark中捕获的大量UDP数据
  • 23.Linux : ftp服务及配置详解
  • (论文速读)DiffusionDet - 扩散模型在目标检测中的开创性应用
  • AI搜索重构下的GEO优化服务商格局观察
  • 李沐-第六章-LeNet训练中的pycharm jupyter-notebook Animator类的显示问题
  • 轻松同步 Outlook 联系人到 Android
  • 深入解析SAE自动驾驶分级标准(0-5级)及典型落地实例
  • Ubuntu 软件源版本不匹配导致的依赖冲突问题及解决方法
  • C++ 23种设计模式的分类总结
  • C++23输出革命:std::print的崛起与工业界标准滞后的现实困境
  • 18.12 BERT问答系统核心难题:3步攻克Tokenizer答案定位与动态填充实战
  • c/c++ UNIX 域Socket和共享内存实现本机通信
  • 2021睿抗决赛 猛犸不上 Ban
  • diffusers库学习--pipeline,模型,调度器的基础使用
  • 深入解析Prompt缓存机制:原理、优化与实践经验
  • Centos9傻瓜式linux部署CRMEB 开源商城系统(PHP)