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

微服务SpringCloud分布式事务之Seata

视频教程:https://www.bilibili.com/video/BV16P63Y3ESq

效果演示

准备的微服务项目调用的链路如下:
在这里插入图片描述

文字描述:

  • gateway模块接收到请求,并发送到order订单模块
  • order订单模块接收到请求,新增一个订单数据后发送一个请求到pay支付模块
  • pay支付模块接收到请求,发送一个模块到account账户模块扣减余额并新增一条支付数据
  • account账户模块接收到请求,扣减账户余额

当我未标记 @GlobalTransactional 注解的时候,如图:
在这里插入图片描述

在这种情况下很理所应当的报错:
在这里插入图片描述

但是我成功的创建了支付信息:
在这里插入图片描述

且成功的扣减了余额:
在这里插入图片描述

只有订单模块的事务时成功的:
在这里插入图片描述

当我修改为使用Seata的分布式事务注解 @GlobalTransactional
在这里插入图片描述

同样发生了错误:
在这里插入图片描述

余额没有扣减:
在这里插入图片描述

没有新增订单信息:
在这里插入图片描述

也没有形成支付信息:
在这里插入图片描述

这证明了分布式事务Seata搭建成功,接下来我们一个一个步骤搭建一下这个框架。

项目准备

之前我有写过一篇关于SpringCloud整合Micrometer做链路追踪的文章,这篇文章当中准备了一个项目。可以使用下面两个连接下载整合了Micrometer但未整合Seata的项目代码(任选一个即可):

  • zip压缩包:https://github.com/xiaohh-me/xiaohh-cloud-micrometer/archive/refs/tags/v1.1.0.zip
  • tar.gz压缩包:https://github.com/xiaohh-me/xiaohh-cloud-micrometer/archive/refs/tags/v1.1.0.tar.gz

也可以选择未整合Micrometer的源代码(任选一个即可):

  • zip压缩包:https://github.com/xiaohh-me/xiaohh-cloud-micrometer/archive/refs/tags/v1.0.0.zip
  • tar.gz压缩包:https://github.com/xiaohh-me/xiaohh-cloud-micrometer/archive/refs/tags/v1.0.0.tar.gz

整合了Seata做分布式事务的代码:

  • zip压缩包:https://github.com/xiaohh-me/xiaohh-cloud-micrometer/archive/refs/tags/v1.2.0.zip
  • tar.gz压缩包:https://github.com/xiaohh-me/xiaohh-cloud-micrometer/archive/refs/tags/v1.2.0.tar.gz

该项目所使用到的技术栈:

技术栈版本
SpringBoot3.2.12
SpringCloud2023.0.4
SpringCloudAlibaba2023.0.1.0
MyBatisStarter3.0.4

因为使用到了3.*版本的SpringBoot,所以你需要安装Java17或更高版本。

搭建Seata分布式事务

Seata的安装和运行

本次安装的Seata版本为 2.2.0 ,下载链接为:https://dist.apache.org/repos/dist/release/incubator/seata/2.2.0/apache-seata-2.2.0-incubating-bin.tar.gz。也可以使用下面这行命令下载:

curl -LO https://dist.apache.org/repos/dist/release/incubator/seata/2.2.0/apache-seata-2.2.0-incubating-bin.tar.gz

然后可以使用下面命令解压,当然在Windows下你也可以使用如360压缩等软件进行解压:

tar -zxvf apache-seata-2.2.0-incubating-bin.tar.gz

解压之后目录如图:
在这里插入图片描述

此次只需要关注到 seata-server 目录的内容即可,目录内容:
在这里插入图片描述

需要修改这个目录下 conf/application.yml 文件,文件内容(注意需要修改nacos注册中心和配置中心,还有数据库配置):

#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

server:
  port: 7091

spring:
  application:
    name: seata-server

logging:
  config: classpath:logback-spring.xml
  file:
    path: ${log.home:${user.home}/logs/seata}
  extend:
    logstash-appender:
      destination: 127.0.0.1:4560
    kafka-appender:
      bootstrap-servers: 127.0.0.1:9092
      topic: logback_to_logstash

console:
  user:
    # 控制台的用户名和密码
    username: seata
    password: seata
seata:
  config:
    # support: nacos, consul, apollo, zk, etcd3
    type: nacos
    nacos:
      # nacos 配置中心配置
      server-addr: 127.0.0.1:8848
      namespace: xiaohh-cloud-dev
      group: SEATA_GROUP
      data-id: seataServer.properties
  registry:
    # support: nacos, eureka, redis, zk, consul, etcd3, sofa
    type: nacos
    nacos:
      # nacos 注册中心配置
      application: seata-server
      server-addr: 127.0.0.1:8848
      group: SEATA_GROUP
      namespace: xiaohh-cloud-dev
      cluster: default
  store:
    # support: file 、 db 、 redis 、 raft
    mode: db
    db:
      # 数据库配置
      datasource: druid
      db-type: mysql
      driver-class-name: com.mysql.jc.jdbc.Driver
      url: jdbc:mysql://127.0.0.1:3306/xiaohh_seata?rewriteBatchedStatements=true
      user: root
      password: xiaohh
      min-conn: 10
      max-conn: 100
      global-table: global_table
      branch-table: branch_table
      lock-table: lock_table
      distributed-lock-table: distributed_lock
      vgroup-table: vgroup_table
      query-limit: 1000
      max-wait: 5000
  #  server:
  #    service-port: 8091 #If not configured, the default is '${server.port} + 1000'
  security:
    secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
    tokenValidityInMilliseconds: 1800000
    csrf-ignore-urls: /metadata/v1/**
    ignore:
      urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.jpeg,/**/*.ico,/api/v1/auth/login,/version.json,/health,/error,/vgroup/v1/**

数据库建表语句可以通过这个地址获得:https://raw.githubusercontent.com/apache/incubator-seata/refs/heads/master/script/server/db/mysql.sql,也可以通过下面命令在已搭建好Seata分布式事务的代码仓库当中也有:
在这里插入图片描述

创建数据库,并执行这个脚本文件,现将命令行的目录移动到项目的sql当中,然后登录mysql并在mysql当中执行下面几行命令(可以改为自己的数据库名字哦):

drop database if exists `xiaohh_seata`;
create database `xiaohh_seata`;
use `xiaohh_seata`;
source seata_server.sql

执行如图:
在这里插入图片描述

然后确定你的seata配置文件没问题之后,先启动nacos,再启动seata。在确保nacos正常启动之后执行下面命令启动seata:

  • Windows:
bin/seata-server.bat
  • Mac/Linux:
./bin/seata-server.sh

Mac启动如图:
在这里插入图片描述

启动之后到对应的nacos命名空间下查看,可以看到seata已经以 seata-server 的名字注册到nacos注册中心中:
在这里插入图片描述

至此,seata安装和启动成功

修改项目代码

添加项目依赖

如果你的项目和我提供的项目一样,在聚合 pom.xml 或着项目的 pom.xml 当中添加了 spring-cloud-alibaba-dependencies 的依赖管理,如图:
在这里插入图片描述

则只需要在参与到分布式事务微服务的 pom.xml 中添加如下依赖即可:

<!-- Seata 分布式事务 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>

添加如图:
在这里插入图片描述

修改bootstrap.yaml配置文件

需要修改参与到分布式事务微服务模块的 bootstrap.yaml 配置文件,告诉微服务模块seata的位置,添加的配置如下:

seata:
  # 数据源代理模式
  data-source-proxy-mode: AT
  registry:
    nacos:
      # seata注册到nacos的配置
      server-addr: 127.0.0.1:8848
      namespace: xiaohh-cloud-dev
      group: SEATA_GROUP
      application: seata-server
    type: nacos
  # 采用默认的事务分组
  service:
    vgroup-mapping:
      default_tx_group: default
  tx-service-group: default_tx_group

添加如图:
在这里插入图片描述

为业务数据库新建表

AT模式分布式事务需要微服务模块的数据库当中有 undo_log 表,这个表存储了如果分布式事务失败了,应该如何回滚数据。这个表的建表语句在 https://raw.githubusercontent.com/apache/incubator-seata/refs/heads/master/script/client/at/db/mysql.sql 当中,也可以复制下面这行建表语句:

-- for AT mode you must to init this sql for you business database. the seata server not need it.
CREATE TABLE IF NOT EXISTS `undo_log`
(
    `branch_id`     BIGINT       NOT NULL COMMENT 'branch transaction id',
    `xid`           VARCHAR(128) NOT NULL COMMENT 'global transaction id',
    `context`       VARCHAR(128) NOT NULL COMMENT 'undo_log context,such as serialization',
    `rollback_info` LONGBLOB     NOT NULL COMMENT 'rollback info',
    `log_status`    INT(11)      NOT NULL COMMENT '0:normal status,1:defense status',
    `log_created`   DATETIME(6)  NOT NULL COMMENT 'create datetime',
    `log_modified`  DATETIME(6)  NOT NULL COMMENT 'modify datetime',
    UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8mb4 COMMENT ='AT transaction mode undo table';
ALTER TABLE `undo_log` ADD INDEX `ix_log_created` (`log_created`);

所有涉及到分布式事务的数据库都需要这张表:
在这里插入图片描述

修改事务注解

接下来来到需要分布式事务的 service 层方法,作者提供的项目该方法为 work.xiaohh.order.service.impl.OrderInfoServiceImpl#insertOrderInfo ,复制前面这段,来到 IDEA 当中双击 Shift 键,在搜索框当中输入即可查询到:
在这里插入图片描述

本方法还是使用Spring的事务注解 @Transactional,无法解决分布式事务问题:
在这里插入图片描述

需要修改为 @GlobalTransactional
在这里插入图片描述

然后在此方法的 return 语句前加上下面这行代码:

if (true) throw new RuntimeException("测试分布式事务失败异常");

添加如图:
在这里插入图片描述

测试分布式事务是否成功

接下来就可以测试分布式事务了,首先发送获取账户余额的请求,可以看到账户余额为10000:
在这里插入图片描述

然后请求分布式事务的接口,可以看到报错了:
在这里插入图片描述

然后再次请求获取账户余额接口,可以看到余额并没有被扣减:
在这里插入图片描述

也没有支付信息的产生:
在这里插入图片描述

可以确定分布式事务搭建成功!

修改报错消息

可以看到请求分布式事务接口时候,报错消息并不是代码中写的分布式消息,而是Seata返回的错误消息:
在这里插入图片描述

需要修改一下统一异常返回 RestControllerAdvice ,将 e.getMessage() 改为 e.getCause().getMessage() 即可,如图:
在这里插入图片描述

然后重启项目再次请求发现改为了代码当中写的Message:
在这里插入图片描述
好了,到此为止Seata分布式事务搭建成功


http://www.kler.cn/a/458948.html

相关文章:

  • Android 15 状态栏闹钟图标不显示问题修复
  • Flink源码解析之:如何根据JobGraph生成ExecutionGraph
  • 40.3 prometheus预聚合源码解读
  • 高等数学学习笔记 ☞ 函数的极限
  • Keil中的gcc
  • TB1801D 线性驱动 LED 恒流芯片
  • 基于Pytorch和yolov8n手搓安全帽目标检测的全过程
  • 闭包的理解
  • 协程原理 函数栈 有栈协程
  • SpringCloudAlibaba 技术栈—Sentinel
  • union的实际使用
  • html+css网页设计 美食 美食4个页面
  • HTML——13.超链接
  • 纯血鸿蒙ArkUI选项卡布局详解
  • 【Spring Boot 实现 PDF 导出】
  • win10、win11-鼠标右键还原、暂停更新
  • Docker运行hello-world镜像失败或超时:Unable to find image ‘hello-world:latest‘ locally Trying to pull reposi
  • Hbase的特点、特性
  • 【Vue】深入理解v-model指令-父子组件数据绑定
  • AI生成视频字幕--VideoCaptioner/卡卡字幕助手
  • 【Java】深入了解 Java 中的 split() 方法
  • 什么是Spring Boot 应用开发?
  • VuePress搭建个人博客
  • 根据 business_group的值在 Django 管理员界面中显示不同字段
  • 智能工厂的设计软件 应用场景的一个例子:为AI聊天工具添加一个知识系统 之7 附件(文档)
  • 项目基本配置