微服务SpringCloud分布式事务之Seata

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: SpringCloud+SpringCloudAlibaba的Seata实现分布式事务,步骤超详细,附带视频教程

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

效果演示

准备的微服务项目调用的链路如下:
image-20241227155515140.png

文字描述:

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

当我未标记 @GlobalTransactional 注解的时候,如图:
image-20241227160218829.png

在这种情况下很理所应当的报错:
image-20241227162207319.png

但是我成功的创建了支付信息:
image-20241227162231372.png

且成功的扣减了余额:
image-20241227162259431.png

只有订单模块的事务时成功的:
image-20241227162326587.png

当我修改为使用Seata的分布式事务注解 @GlobalTransactional
image-20241227162738585.png

同样发生了错误:
image-20241227163002018.png

余额没有扣减:
image-20241227163021169.png

没有新增订单信息:
image-20241227163100289.png

也没有形成支付信息:
image-20241227163120722.png

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

项目准备

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

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

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

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

技术栈 版本
SpringBoot 3.2.12
SpringCloud 2023.0.4
SpringCloudAlibaba 2023.0.1.0
MyBatisStarter 3.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

解压之后目录如图:
image-20241227174339607.png

此次只需要关注到 seata-server 目录的内容即可,目录内容:
image-20241227182203987.png

需要修改这个目录下 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分布式事务的代码仓库当中也有:
image-20241227195709868.png

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

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

执行如图:
image-20241227202640592.png

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

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

Mac启动如图:
image-20241227204723382.png

启动之后到对应的nacos命名空间下查看,可以看到seata已经以 seata-server 的名字注册到nacos注册中心中:
image-20241227205051675.png

至此,seata安装和启动成功

修改项目代码

添加项目依赖

如果你的项目和我提供的项目一样,在聚合 pom.xml 或着项目的 pom.xml 当中添加了 spring-cloud-alibaba-dependencies 的依赖管理,如图:
image-20241227210319772.png

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

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

添加如图:
image-20241227210702444.png

修改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

添加如图:
image-20241227213154866.png

为业务数据库新建表

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`);

所有涉及到分布式事务的数据库都需要这张表:
image-20241227221419212.png

修改事务注解

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

本方法还是使用Spring的事务注解 @Transactional,无法解决分布式事务问题:
image-20241227213911325.png

需要修改为 @GlobalTransactional
image-20241227214324151.png

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

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

添加如图:
image-20241227215233270.png

测试分布式事务是否成功

接下来就可以测试分布式事务了,首先发送获取账户余额的请求,可以看到账户余额为10000:
image-20241227221803587.png

然后请求分布式事务的接口,可以看到报错了:
image-20241227221859143.png

然后再次请求获取账户余额接口,可以看到余额并没有被扣减:
image-20241227221944567.png

也没有支付信息的产生:
image-20241227222014616.png

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

修改报错消息

可以看到请求分布式事务接口时候,报错消息并不是代码中写的分布式消息,而是Seata返回的错误消息:
image-20241227221859143.png

需要修改一下统一异常返回 RestControllerAdvice ,将 e.getMessage() 改为 e.getCause().getMessage() 即可,如图:
image-20241227222726842.png

然后重启项目再次请求发现改为了代码当中写的Message:
image-20241227223014306.png

好了,到此为止Seata分布式事务搭建成功

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
10天前
|
JSON Java API
利用Spring Cloud Gateway Predicate优化微服务路由策略
Spring Cloud Gateway 的路由配置中,`predicates`​(断言)用于定义哪些请求应该匹配特定的路由规则。 断言是Gateway在进行路由时,根据具体的请求信息如请求路径、请求方法、请求参数等进行匹配的规则。当一个请求的信息符合断言设置的条件时,Gateway就会将该请求路由到对应的服务上。
112 69
利用Spring Cloud Gateway Predicate优化微服务路由策略
|
29天前
|
Java 开发者 微服务
从单体到微服务:如何借助 Spring Cloud 实现架构转型
**Spring Cloud** 是一套基于 Spring 框架的**微服务架构解决方案**,它提供了一系列的工具和组件,帮助开发者快速构建分布式系统,尤其是微服务架构。
158 69
从单体到微服务:如何借助 Spring Cloud 实现架构转型
|
27天前
|
Java Nacos Sentinel
Spring Cloud Alibaba:一站式微服务解决方案
Spring Cloud Alibaba(简称SCA) 是一个基于 Spring Cloud 构建的开源微服务框架,专为解决分布式系统中的服务治理、配置管理、服务发现、消息总线等问题而设计。
213 13
Spring Cloud Alibaba:一站式微服务解决方案
|
13天前
|
Java 关系型数据库 Nacos
微服务SpringCloud链路追踪之Micrometer+Zipkin
SpringCloud+Openfeign远程调用,并用Mircrometer+Zipkin进行链路追踪
126 20
|
27天前
|
消息中间件 SQL 中间件
大厂都在用的分布式事务方案,Seata+RocketMQ带你打破10万QPS瓶颈
分布式事务涉及跨多个数据库或服务的操作,确保数据一致性。本地事务通过数据库直接支持ACID特性,而分布式事务则需解决跨服务协调难、高并发压力及性能与一致性权衡等问题。常见的解决方案包括两阶段提交(2PC)、Seata提供的AT和TCC模式、以及基于消息队列的最终一致性方案。这些方法各有优劣,适用于不同业务场景,选择合适的方案需综合考虑业务需求、系统规模和技术团队能力。
183 7
|
4月前
|
SpringCloudAlibaba API 开发者
新版-SpringCloud+SpringCloud Alibaba
新版-SpringCloud+SpringCloud Alibaba
|
11天前
|
SpringCloudAlibaba 负载均衡 Dubbo
【SpringCloud Alibaba系列】Dubbo高级特性篇
本章我们介绍Dubbo的常用高级特性,包括序列化、地址缓存、超时与重试机制、多版本、负载均衡。集群容错、服务降级等。
【SpringCloud Alibaba系列】Dubbo高级特性篇
|
11天前
|
存储 SpringCloudAlibaba Java
【SpringCloud Alibaba系列】一文全面解析Zookeeper安装、常用命令、JavaAPI操作、Watch事件监听、分布式锁、集群搭建、核心理论
一文全面解析Zookeeper安装、常用命令、JavaAPI操作、Watch事件监听、分布式锁、集群搭建、核心理论。
【SpringCloud Alibaba系列】一文全面解析Zookeeper安装、常用命令、JavaAPI操作、Watch事件监听、分布式锁、集群搭建、核心理论
|
11天前
|
SpringCloudAlibaba JavaScript Dubbo
【SpringCloud Alibaba系列】Dubbo dubbo-admin安装教程篇
本文介绍了 Dubbo-Admin 的安装和使用步骤。Dubbo-Admin 是一个前后端分离的项目,前端基于 Vue,后端基于 Spring Boot。安装前需确保开发环境(Windows 10)已安装 JDK、Maven 和 Node.js,并在 Linux CentOS 7 上部署 Zookeeper 作为注册中心。
【SpringCloud Alibaba系列】Dubbo dubbo-admin安装教程篇
|
11天前
|
SpringCloudAlibaba Dubbo Java
【SpringCloud Alibaba系列】Dubbo基础入门篇
Dubbo是一款高性能、轻量级的开源Java RPC框架,提供面向接口代理的高性能RPC调用、智能负载均衡、服务自动注册和发现、运行期流量调度、可视化服务治理和运维等功能。
【SpringCloud Alibaba系列】Dubbo基础入门篇