• Spring Cloud Alibaba Seata 搭建以及分布式事务的验证


    Spring Cloud Alibaba Seata 搭建以及分布式事务的验证

    1.seata 简介

    • Seata(Simple Extensible Autonomous Transaction Architecture)是一种开源的分布式事务解决方案,旨在解决微服务架构下的分布式事务问题。它提供了一套完整的分布式事务管理功能,包括全局事务管理、本地事务协调和分布式事务恢复等。
    • 在传统的单体应用中,使用关系型数据库的事务机制可以确保数据的一致性和隔离性。然而,在微服务架构中,每个微服务都有自己独立的数据库,无法直接使用传统事务进行跨服务的一致性控制。这就导致了分布式事务的挑战。
    • Seata 提供了分布式事务的解决方案,通过引入一个事务协调器(Transaction Coordinator)来协调多个参与者(Participants)之间的本地事务。Seata 支持两阶段提交(Two-Phase Commit)和补偿事务(Compensating Transaction)两种模式。
    • 在 Seata 的架构中,事务发起者(Transaction Coordinator)负责全局事务的创建、提交和回滚,并协调各个参与者的事务操作。参与者(Participants)执行具体的本地事务操作,并与事务协调器进行通信。事务管理器(Transaction Manager)负责协调全局和本地事务的提交和回滚,以及事务的状态管理。
    • Seata 提供了与各种主流数据库和框架的集成支持,例如 MySQL、Oracle、Spring Boot 等,使得在现有的微服务架构中引入分布式事务变得更加方便。

    2. seata的三大角色

    • 事务协调者(Transaction Coordinator,TC)- 维护全局和分支事务的状态,驱动全局事务提交或回滚,是整个分布式事务的核心。
    • 事务管理器(Transaction Manager,TM)- 定义全局事务的范围,开始全局事务、提交或回滚全局事务。
    • 资源管理器(Resource Manager,RM)- 管理分支事务处理的资源,与 TC 交流以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
    • 其中,TC 是单独部署的 Server 服务端,TM 和 RM 则是嵌入到应用中的 Client 客户端。由于 TC 是独立的服务端,它与 TM 和 RM 进行通信的接口被称为 RPC(Remote Procedure Call,远程过程调用)接口。具体来讲,TM 和 RM 向 TC 发送关于事务的请求,TC 则根据请求的类型进行相应的响应和操作,从而实现分布式事务的一致性和可靠性。

    在这里插入图片描述

    3. Seata的流程

    • TM发起一个全局事务请求,请求TC开启一个全局事务。TC为该全局事务生成一个全局唯一的事务ID(XID)gloab_table就是存储的全局事务信息。
    • RM将本地事务注册为该全局事务的分支事务,并通过XID进行关联。RM会与TC进行通信,报告分支事务的状态,分支事务存储在brance_table。
    • TM根据业务逻辑执行相关操作,操作涉及的资源由RM管理。
    • 当TM完成所有操作后,请求TC提交或回滚该全局事务。TC收到请求后,驱动所有参与者(RM)执行相应的提交或回滚操作。每个参与者根据TC的指令将其本地事务提交或回滚

    4. Seata AT模式

    • 第一阶段
      业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。核心在于对业务sql进行解析,转换成undolog.
      AT模式官方网址

    • 第二阶段
      1.分布式事务操作成功,则TC通知RM异步删除undolog
      2.分布式事务操作失败,TM向TC发送回滚请求,RM 收到协调器TC发来的回滚请求,通过 XID 和 Branch ID 找到相应的回滚日志记录,通过回滚记录生成反向的更新 SQL 并执行,以完成分支的回滚。

    • 优势
      应用层基于SQL解析实现了自动补偿,从而最大程度的降低业务侵入性;
      将分布式事务中TC(事务协调者)独立部署,负责事务的注册、回滚;
      通过全局锁实现了写隔离与读隔离。

    5. Seata搭建

    下载seata1.3版本
    修改file.conf
    在这里插入图片描述

    修改register.conf
    在这里插入图片描述

    找到模板案例,照着抄

    案例需要vpn
    在这里插入图片描述

    复制数据库创建语句自己创建出来,作为保存相关必要的数据
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    csdn不让上传文件,我将所有需要的文件打包放入网盘
    这里的两个文件也在里面
    在这里插入图片描述
    运行刚才放入的文件
    注意nacos这里默认是开启的

      sh nacos-config.sh -h 192.168.14.3  -p 8848 -g SEATA_GROUP
    
    • 1

    可在windows客户端中查看相应刚刚配置的文件
    搭建的nacos的ip加上端口号,必须加上/nacos 账号密码均为nacos
    在这里插入图片描述
    需要修改
    在刚刚打开的网页中找到并修改记得一定要修改时区

    • url

        jdbc:mysql://192.168.14.53:3306/seata——global?useUnicode=true&serverTimezone=UTC
      
      • 1

    username,和password改为自己的
    在这里插入图片描述
    启动服务
    在这里插入图片描述
    使用这个命令记得改java的环境变量为java8.

     bin/seata-server.sh   -p 8091  -n 1 
     bin/seata-server.sh   -p 8092  -n 2
    
    • 1
    • 2

    在这里插入图片描述

    6. Seata Client快速开始

    6.1 声明式事务实现(@GlobalTransactional)

    接入微服务应用
    业务场景:
    用户下单,整个业务逻辑由两个微服务构成:

    • 订单服务:根据采购需求创建订单。
    • 库存服务:对给定的商品扣除库存数量。

    6.2 添加依赖

    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
    </dependency>
    
    • 1
    • 2
    • 3
    • 4

    6.3 各微服务对应配置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,
      PRIMARY KEY (`id`),
      UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    6.4 测试

    1. 订单

    调用方法后 通过openfeign调用 stock-app的stock接口 记得检查是否注入

    @RestController
    public class OrderController {
        @Autowired
        OrderItemDao orderItemDao;
    
        @Autowired
        OrderDao orderDao;
        @Autowired
        StockClient stockClient;
    
        @PostMapping("/add")
        @GlobalTransactional(name = "addOrder")
        public String add(@RequestBody Ordering ordering){
            String yy = DateUtil.format(DateUtil.date(), "YYYYMMDDHHmmssSSS");
            Long aLong = Long.valueOf(yy);
            ordering.setId(aLong);
            orderDao.addOrderMaster(ordering);
            List<OrderingProduct> products = ordering.getProducts();
            for(OrderingProduct product : products){
                product.setOrderId(aLong);
                orderItemDao.addOrderItem(product);
                stockClient.upQty(product.getProductId(),product.getQty());
            }
            return "yes";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    这是调用的方法

    @GetMapping("/stock")
        @GlobalTransactional(name = "addOrder")
        public String upQty(Integer productId,Integer qty){
            int a = 5/0;
            inventoryDao.updateQty(qty,productId);
            inventoryLogDao.log("产品ID为" + productId + "减少数量" + qty);
    
            return null;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    6.6 只需要一个公共注解代替原始注解

    @GlobalTransactional(name = “addOrder”)
    俩个一定要有相同的名字,可以共同成功,共同失败

  • 相关阅读:
    AH8691-60V降压至3.3V电源芯片:ESOP8封装解决方案
    day56,ARM day3:寄存器内存读写指令
    如何使用AI图片清晰度增强器软件增强和锐化图片、提高照片清晰度并去除噪点
    30秒让你弄懂pdf怎么翻译,还在犹豫什么
    Mysql 索引使用总结
    2023.10.17
    MySQL——事务
    【JAVA】栈和队列(Part2 队列)
    信创操作系统--麒麟Kylin桌面操作系统 (项目十二 使用Systemd管理系统服务)
    单目深度估计: LDRN网络及代码讲解
  • 原文地址:https://blog.csdn.net/weixin_63558979/article/details/133276071