seata分布式事务之AT模式实践代码

news2025/6/8 20:18:13

seata框架

AT模式:

先添加seata需要的数据库相关表,AT模式需要在每个业务所属库下建undo_log表,用来回滚的,出错seata就会从这个表生成反向sql回退数据

在这里插入图片描述

建表语句:

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for undo_log
-- ----------------------------
DROP TABLE IF EXISTS `undo_log`;
CREATE TABLE `undo_log`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `branch_id` bigint(20) NOT NULL,
  `xid` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `context` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `rollback_info` longblob NOT NULL,
  `log_status` int(11) NOT NULL,
  `log_created` datetime(0) NOT NULL,
  `log_modified` datetime(0) NOT NULL,
  `ext` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE INDEX `ux_undo_log`(`xid`, `branch_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

在每个业务库下建完undo_log后,需要建一个seata服务所用的库,我这里就叫seata库

在这里插入图片描述

建表语句:(注意我这个是1.6.1版本的表,可能和旧版本的字段长度什么的有差异,因为我之前随便找了sql跑seata就是报错,具体没去研究)

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for branch_table
-- ----------------------------
DROP TABLE IF EXISTS `branch_table`;
CREATE TABLE `branch_table`  (
  `branch_id` bigint(20) NOT NULL,
  `xid` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `transaction_id` bigint(20) DEFAULT NULL,
  `resource_group_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  `resource_id` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  `branch_type` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  `status` tinyint(4) DEFAULT NULL,
  `client_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  `application_data` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  `gmt_create` datetime(6) DEFAULT NULL,
  `gmt_modified` datetime(6) DEFAULT NULL,
  PRIMARY KEY (`branch_id`) USING BTREE,
  INDEX `idx_xid`(`xid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Table structure for distributed_lock
-- ----------------------------
DROP TABLE IF EXISTS `distributed_lock`;
CREATE TABLE `distributed_lock`  (
  `lock_key` char(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `lock_value` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `expire` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`lock_key`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Table structure for global_table
-- ----------------------------
DROP TABLE IF EXISTS `global_table`;
CREATE TABLE `global_table`  (
  `xid` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `transaction_id` bigint(20) DEFAULT NULL,
  `status` tinyint(4) NOT NULL,
  `application_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  `transaction_service_group` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  `transaction_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  `timeout` int(11) DEFAULT NULL,
  `begin_time` bigint(20) DEFAULT NULL,
  `application_data` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  `gmt_create` datetime(0) DEFAULT NULL,
  `gmt_modified` datetime(0) DEFAULT NULL,
  PRIMARY KEY (`xid`) USING BTREE,
  INDEX `idx_status_gmt_modified`(`status`, `gmt_modified`) USING BTREE,
  INDEX `idx_transaction_id`(`transaction_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Table structure for lock_table
-- ----------------------------
DROP TABLE IF EXISTS `lock_table`;
CREATE TABLE `lock_table`  (
  `row_key` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `xid` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  `transaction_id` bigint(20) DEFAULT NULL,
  `branch_id` bigint(20) NOT NULL,
  `resource_id` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  `table_name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  `pk` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  `status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '0:locked ,1:rollbacking',
  `gmt_create` datetime(0) DEFAULT NULL,
  `gmt_modified` datetime(0) DEFAULT NULL,
  PRIMARY KEY (`row_key`) USING BTREE,
  INDEX `idx_status`(`status`) USING BTREE,
  INDEX `idx_branch_id`(`branch_id`) USING BTREE,
  INDEX `idx_xid`(`xid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

接下来采用nacos作为注册中心和配置中心,seata解压后修改conf下的application.yml

样例:

#  Copyright 1999-2019 Seata.io Group.
#
#  Licensed 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: ${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: #配置中心,这里指定nacos
    # support: nacos, consul, apollo, zk, etcd3
    type: nacos
    nacos:
          serverAddr: 127.0.0.1:8848
          group:  SEATA_GROUP #nacos上的配置所属分组
          username: ""#nacos这里未开启验证无所谓配不配
          password: ""
          # data-id: seataServer.properties #我测的这个版本1.6.1将官方的config.txt写在这个里seata读不到,不知道原因,后采用旧版本seata的配置方式
          namespace: d23703ee-09aa-444b-83b5-1c7f8ca7a4a7 #配置的命名空间,需要现在nacos中新建命名空间
  registry:#nacos上的服务注册中心
    # support: nacos, eureka, redis, zk, consul, etcd3, sofa
    type: nacos #类别选择nacos
    nacos: 
          application: seata-server #注册到nacos上的服务名
          serverAddr: 127.0.0.1:8848
          group: SEATA_GROUP #服务所属组
          namespace: d23703ee-09aa-444b-83b5-1c7f8ca7a4a7 #所属命名空间,这里和配置所属的命名空间要一样
          username: ""#nacos这里未开启验证无所谓配不配
          password: ""



########这里的store我配了但是seata好像读不到,不知道为什么,后面还是在nacos上配的
  store:
    # support: file 、 db 、 redis
    mode: db
    db:
      db-type: mysql
      datasourcec: druid
      driverClassName: com.mysql.jdbc.Driver
      url: jdbc:mysql://localhost:3306/seata?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
      user: root
      password: root
##############################################      
#  server:
#    service-port: 8091 #If not configured, the default is '${server.port} + 1000'
  security:
    secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
    tokenValidityInMilliseconds: 1800000
    ignore:
      urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/api/v1/auth/login

修改完application.yml后windows直接启动bin下的bat文件,然后可以看到nacos上由seata-server注册上来

在这里插入图片描述

然后到配置中心取做配置
在这里插入图片描述

注意,service.vgroupMapping.xxx,这个xxx很重要,对应意思是事务分组,

我以service.vgroupMapping.default_tx_group为例,这个default_tx_group也是1.6.1版本默认的配置

在这里插入图片描述

这里的default其实在seata启动的application.yml中可以配其他的,对应的是这个值

在这里插入图片描述

不配的话默认也是default,像上文我就没额外自己配

到这里seata-server端就启动好了,这里nacos更新配置文件seata是会动态更新的不用重启

接下来是客户端集成,就是微服务中集成seata模块

这边我以商品订单余额为例:

在这里插入图片描述

三个微服务,都注册在nacos上,分别为三个独立数据库

在这里插入图片描述

我的调用顺序为:减库存->减余额->创建订单

减库存接口:

   @Autowired
    ReduceGoodsService reduceGoodsService;

    @RequestMapping("/reduceGoods/{goodsId}")
    public String reduceGoods(@PathVariable("goodsId")String goodsId){
        System.out.println("调用扣减库存");
        int i = reduceGoodsService.reduceGoodsCount(goodsId);
        if (i==1){
            return "扣减库存成功";
        }
        else {
            return "扣减库存失败";
        }
    }

减余额接口:

  @Autowired
    ReduceMoneyService reduceMoneyService;

    @RequestMapping("/reduceMoney/{userId}")
    public String reduceMoney(@PathVariable("userId")String userId){
        System.out.println("调用扣减余额");
        int i = reduceMoneyService.reduceRestMoney(userId);

        if (i==1){
            return "扣减库存成功";
        }
        else {
            return "扣减库存失败";
        }
    }

创建订单接口:

  	@GlobalTransactional(rollbackFor = Exception.class)//这是全局事务注解***
    @RequestMapping("/createOrder/{userId}/{goodsId}/{goodsCount}")
    public void createOrder(@PathVariable("userId")String userId,@PathVariable("goodsId")String goodsId,@PathVariable("goodsCount")String goodsCount){


        //减库存
        String reduceGoodsUrl="http://"+"reduceGoods"+"/reduceGoods/"+goodsId;
        restTemplate.getForObject(reduceGoodsUrl, String.class);

        //减余额
        String reduceMoneyUrl="http://"+"reduceMoney"+"/reduceMoney/"+userId;
        restTemplate.getForObject(reduceMoneyUrl, String.class);

        createOrderService.createOrder(UUID.randomUUID().toString(),userId, goodsId, goodsCount);



    }

接下是重要的配置文件,以扣余额为例

server:
  port: 2222
spring:
  application:
    name: reduceMoney
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
        ip: 127.0.0.1
        register-enabled: true
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/users?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
    username: root
    password: root
    type: com.alibaba.druid.pool.DruidDataSource

mybatis:
  mapper-locations: classpath:mappers/*.xml
  configuration:
    map-underscore-to-camel-case: true
##########################################以上是注册服务到nacos等的相关配置,主要关注下面的seata
seata:
  enable-auto-data-source-proxy: true   #默认开启,如果要手动配configuration中的datasource的话要设为false
  enabled: true
  tx-service-group: default_tx_group  #这个要和上文在nacos上注册的service.vgroupMapping.xxx中的xxx一致
  ##############################下面这部分和seata自己的那部分配置一样
  config:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      group: SEATA_GROUP
      namespace: d23703ee-09aa-444b-83b5-1c7f8ca7a4a7
  registry:
    type: nacos
    nacos:
        application: seata-server
        server-addr: 127.0.0.1:8848
        group: SEATA_GROUP
        namespace: d23703ee-09aa-444b-83b5-1c7f8ca7a4a7
        username: ""
        password: ""
  ###################################
  service:
    # 事务组对应的集群名称
    vgroupMapping:
      default_tx_group: default  #这个default_tx_group和上面一样配你配在nacos中的service.vgroupMapping.xxx中的xxx一致


其他模块的seata配置和这个一样

接下来启动三个模块,然后调用,如果发现有异常,那seata会回退全局事务

在日志中体现为
在这里插入图片描述

如果全局事务提交成功,日志体现为
在这里插入图片描述

另外,在三个模块启动时,会分别注册到seata中去,日志体现为:

附录:一些坑:

如果模块启动报找不到service.vgroupMapping.xxxx大概率是配置中心配的不对,就是那个service.vgroupMapping.xxxx属性,然后服务模块中的yml一定要配这个

 ###################################
  service:
    # 事务组对应的集群名称
    vgroupMapping:
      default_tx_group: default 

业务表如果没主键,或者主键是自增的好像seata是不能用的,如果你的整理业务流程中,涉及到error你去捕获了但是不抛出来,那seata是不会认为报错的,也就不会回滚,用try catch的话一定要throw出来

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/334414.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

持续集成Jenkins (四)Jenkins+git+maven项目构建、自动化部署

GIT配置1.1 前言:需要安装 git 客户端.yum install git1.2 Jenkins 配置插件 Git 在仪表盘选择Manage Jenkins>>Plugin Manager>>进入如下页面,可以选择可选的插件,安装完成后的插件在installed里面可以看到,我这里已…

DataFrame与Spark SQL的由来

文章目录DataFrame与Spark SQL的由来RDD 之殇:优化空间受限DataFrame 横空出世幕后英雄:Spark SQL基于 DataFrame,Spark SQL 是如何进行优化的Catalyst 优化器TungstenDataFrame与Spark SQL的由来 Spark 已经有了 RDD 这个开发入口&#xff…

市场最快图表:LightningChart .NET v.10.4.1 Crack

LightningChart .NET v.10.4.1 已经发布! 新功能、新自定义控件和性能改进 DataCursor:图表中自动数据跟踪的新功能。 在以前的版本中,LightningChart .NET 提供了不同的工具来实现数据跟踪功能,但是这些需要用户进行一些额外的编…

Python-第一天 安装Python和PyCharm

Python-第一天 安装Python和PyCharm一、安装Python1. 下载2. 安装3.验证是否安装成功二、安装和配置PyCharm工具1.下载2.安装3.创建工程4.配置4.1 修改主题4.2 修改默认字体和大小4.3 通过快捷键快速设置字体大小4.4 汉化软件4.5 其它插件4.6 常用快捷建一、安装Python 1. 下载…

计算机图形学02:中点BH算法绘制直线

作者:非妃是公主 专栏:《计算机图形学》 博客地址:https://blog.csdn.net/myf_666 个性签:顺境不惰,逆境不馁,以心制境,万事可成。——曾国藩 文章目录专栏推荐专栏系列文章序一、算法原理二、缺…

计算机科学基础知识第二节讲义

课程链接 运行环境:WSL Ubuntu OMZ终端 PS:看到老师终端具有高亮和自动补全功能,我连夜肝出oh-my-zsh安装教程,实现了此功能。 这节课主要讲变量的语法、控制流程、shell功能等内容。 修改终端用户名,输入密码后重启…

全国青少年编程等级考试scratch三级真题2022年9月(含题库答题软件账号)

青少年编程等级考试scratch真题答题考试系统请点击电子学会-全国青少年编程等级考试真题Scratch一级(2019年3月)在线答题_程序猿下山的博客-CSDN博客_小航答题助手1运行下列程序后,结果为120的是?( )A.B.C…

英语学习:每日翻译

World in a dish盘中知世界 1 How to eat to 100 如何吃到100岁 2 Dan Buettner’s book explores America’s healthiest cuisines 丹比特纳的书探索了美国最健康的美食 注意: 1 cuisines 美食3 Nearly 70% of American adults are overweight; over a thir…

python接口自动化(十)--post请求四种传送正文方式(详解)

简介 post请求我在python接口自动化(八)--发送post请求的接口(详解)已经讲过一部分了,主要是发送一些较长的数据,还有就是数据比较安全等。我们要知道post请求四种传送正文方式首先需要先了解一下常见的四种…

游戏服务器性能测试分析实战

今天遇到一个性能压测的问题,也是很多同学做游戏服务器开发经常会遇到的,今天记录一下分享给大家。 性能压测遇到的问题 对啦!这里有个游戏开发交流小组里面聚集了一帮热爱学习游戏的零基础小白,也有一些正在从事游戏开发的技术大…

Prometheus node_exporter 部署

Prometheus node_exporter 安装包下载 Prometheus 官网下载地址 包含Prometheus软件及各种exporter插件 node_exporter1.4.0安装包 解压安装 tar -xvf node_exporter-1.4.0.linux-amd64.tar.gz注册服务 可参考 linux 自定义服务 vi /etc/init.d/promethues#!/bin/bash …

python selenium浏览器复用技术

使用selenium 做web自动化的时候,经常会遇到这样一种需求,是否可以在已经打开的浏览器基础上继续运行自动化脚本? 这样前面的验证码登录可以手工点过去,后面页面使用脚本继续执行,这样可以解决很大的一个痛点。 命令行…

Spring 5

文章目录传统JavaWeb开发的困惑IoC、DI和Aop思想提出Spring框架的诞生Spring 框架概述Spring 框架历史Spring Framework技术栈图示BeanFactory 快速入门基于xml的Spring应用基于注解的Spring应用传统JavaWeb开发的困惑 IoC、DI和Aop思想提出 Spring框架的诞生 Spring 框架概述 …

Ansys Lumerical | 纳米线栅偏振器仿真应用

说明 由亚波长金属光栅(纳米线栅偏振器)组成的高对比度偏振控制器件正在取代体光学元件。纳米线栅偏振器提供了较好的消光比对比度、最小的吸收以解决高亮度照明,以及紧凑的形状以便于大规模制造和集成在小型光学器件中。然而,纳米…

代谢组学Nature子刊!抑郁症居然“男女有别”,脑膜淋巴管起关键作用!

文章标题:A functional role of meningeal lymphatics in sex difference of stress susceptibility in mice 发表期刊:Nature Communications 影响因子:17.694 发表时间:2022年8月 作者单位:中山大学中山医学院 …

三层交换机【实验】

目录 1、要求: 2、拓扑: 3、创建vlan和端口定义并划入vlan: 4、创建以太网中继Eth-Trunk使sw1和sw2的相互冗余并且不浪费链路: 5、使用mstp定义组和对应的根: 6、配置网关冗余: 7、核心层的路由的IP配…

基于蜣螂算法改进的DELM分类-附代码

蜣螂算法改进的深度极限学习机DELM的分类 文章目录蜣螂算法改进的深度极限学习机DELM的分类1.ELM原理2.深度极限学习机(DELM)原理3.蜣螂算法4.蜣螂算法改进DELM5.实验结果6.参考文献7.Matlab代码1.ELM原理 ELM基础原理请参考:https://blog.c…

为什么越来越多的团队选择放弃Jira?有哪些替代产品?

国产类似Jira 的软件包括:1.一站式研发项目管理软件 PingCode;2.通用型项目协作工具 Worktile;3.开源项目管理软件 Redmine;4.免费项目管理软件 Trello;5.无代码项目管理软件 Moday;6.小团队项目管理软件 T…

《嵌入式 – GD32开发实战指南》第22章 SPI

开发环境: MDK:Keil 5.30 开发板:GD32F207I-EVAL MCU:GD32F207IK 22.1 SPI简介 SPI,是Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口。是Motorola首先在其MC68HCXX系列处理器上定义的…

Git修改已有仓库的默认分支并删除其他分支

Git仓库中有一个分支没有用,打算删除掉,查找解决办法,儒雅的烤地瓜 的一篇博客1很详细,我按照他的第三点命令敲入,结果出现报错。 查看博客在git push origin --delete main 这条命令前说了:要删除的分支可…