使用Seata解决分布式事务问题

说明:在分布式架构下,一个请求需要多个微服务来实现。当一个请求牵扯到多个微服务时,事务问题就变得麻烦起来。

问题描述

现在有三个服务,分别是账户服务、库存服务和订单服务,生成一个订单,需要确保商品的库存是否充足,账户的余额是否充足,实际操作的是三条语句(添加订单、修改账户余额、修改库存数量),这三条语句组成一个事务。

在这里插入图片描述

例如,2.3 库存不充足,修改数据库库存数量时报错,此时对账户表的操作,对订单表的新增订单操作均已完成,正常业务逻辑是需要将此次业务相关的操作全部回退。

业务代码

Step1:数据库相关表初始状态

在这里插入图片描述

Step2:创建订单代码

在这里插入图片描述

Step3:发送请求

请求数量大于库存数量

在这里插入图片描述

Step4:请求出错

在这里插入图片描述

库存为正整数,修改后结果小于0,修改出错;

在这里插入图片描述

Step5:数据库状态变化

金额已扣除,事务未完全回滚

在这里插入图片描述

解决方案

可以使用Seata技术解决,Seata是蚂蚁金服和阿里巴巴共同开源的,致力于提供高性能和简单医用的分布式事务服务,解决分布式事务问题。

Seata解决分布式事务问题,简单来说,是建立了一个TC(事务协调者,Transaction Coordinator),用来维护全局和分支事务的状态,协调全局事务提交/回滚,如下图:
在这里插入图片描述

图中的TM(事务管理器,Transaction Manager)可以理解为@GlobalTransactional注解标志的范围,如上面的新建订单方法;RM(Resource Manager,资源管理器)表示分支事务所管理的资源,可以简单理解为分支事务所控制的数据库表;

而Seata分布式事务具体实现分为有四种模式,特点如下:

在这里插入图片描述

本文详细介绍前两种模式的使用,其他请参考:http://t.csdn.cn/XZotl

代码实现

第一步:添加依赖

使用Seata前,先添加依赖,因为每个微服务都需要添加,我这里添加到父模块中。

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
    <exclusions>
        <!--版本较低,1.3.0,因此排除-->
        <exclusion>
            <artifactId>seata-spring-boot-starter</artifactId>
            <groupId>io.seata</groupId>
        </exclusion>
    </exclusions>
</dependency>
<!--seata starter 采用1.4.2版本-->
<dependency>
    <groupId>io.seata</groupId>
    <artifactId>seata-spring-boot-starter</artifactId>
    <version>${seata.version}</version>
</dependency>

第二步:设置配置文件

设置seata的配置文件,注意每一个服务模块都需要添加

seata:
  registry: # TC服务注册中心的配置,微服务根据这些信息去注册中心获取tc服务地址
    # 参考tc服务自己的registry.conf中的配置
    type: nacos
    nacos: # tc
      server-addr: 127.0.0.1:8848
      namespace: ""
      group: DEFAULT_GROUP
      application: seata-tc-server # tc服务在nacos中的服务名称
      cluster: SH
  tx-service-group: seata-demo # 事务组,根据这个获取tc服务的cluster名称
  service:
    vgroup-mapping: # 事务组与TC服务cluster的映射关系
      seata-demo: SH

添加配置时,可敲一下“seata”看idea有没有提示,验证依赖是否添加进来了;

在这里插入图片描述

第三步:设置seata配置文件

在nacos上设置seata的配置文件,详细参考:http://t.csdn.cn/MOuRz;

在这里插入图片描述

第四步:创建数据库

为seata创建一个专门的数据库,用来记录事务信息,数据库名要与nacos上配置的数据库名一致
在这里插入图片描述

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;


# 分支事务信息
DROP TABLE IF EXISTS `branch_table`;
CREATE TABLE `branch_table`  (
  `branch_id` bigint(20) NOT NULL,
  `xid` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `transaction_id` bigint(20) NULL DEFAULT NULL,
  `resource_group_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `resource_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `branch_type` varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `status` tinyint(4) NULL DEFAULT NULL,
  `client_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `application_data` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `gmt_create` datetime(6) NULL DEFAULT NULL,
  `gmt_modified` datetime(6) NULL DEFAULT NULL,
  PRIMARY KEY (`branch_id`) USING BTREE,
  INDEX `idx_xid`(`xid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;


# 全局事务信息
DROP TABLE IF EXISTS `global_table`;
CREATE TABLE `global_table`  (
  `xid` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `transaction_id` bigint(20) NULL DEFAULT NULL,
  `status` tinyint(4) NOT NULL,
  `application_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `transaction_service_group` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `transaction_name` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `timeout` int(11) NULL DEFAULT NULL,
  `begin_time` bigint(20) NULL DEFAULT NULL,
  `application_data` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `gmt_create` datetime NULL DEFAULT NULL,
  `gmt_modified` datetime NULL DEFAULT NULL,
  PRIMARY KEY (`xid`) USING BTREE,
  INDEX `idx_gmt_modified_status`(`gmt_modified`, `status`) USING BTREE,
  INDEX `idx_transaction_id`(`transaction_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;


# 全局锁信息
DROP TABLE IF EXISTS `lock_table`;
CREATE TABLE `lock_table`  (
  `row_key` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `xid` varchar(96) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `transaction_id` bigint(20) NULL DEFAULT NULL,
  `branch_id` bigint(20) NOT NULL,
  `resource_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `table_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `pk` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `gmt_create` datetime NULL DEFAULT NULL,
  `gmt_modified` datetime NULL DEFAULT NULL,
  PRIMARY KEY (`row_key`) USING BTREE,
  INDEX `idx_branch_id`(`branch_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;


SET FOREIGN_KEY_CHECKS = 1;

第五步:创建快照表

创建一个表(updo_log),用来记录数据快照的信息,该表创建在业务的数据库内;

在这里插入图片描述

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

DROP TABLE IF EXISTS `undo_log`;
CREATE TABLE `undo_log`  (
  `branch_id` bigint(20) NOT NULL COMMENT 'branch transaction id',
  `xid` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'global transaction id',
  `context` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci 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 INDEX `ux_undo_log`(`xid`, `branch_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'AT transaction mode undo table' ROW_FORMAT = Compact;

SET FOREIGN_KEY_CHECKS = 1;

AT 模式(默认)

原理图

AT模式的特点是,先执行SQL,当分支事务有失败时,再根据数据快照回滚数据。

在这里插入图片描述

第一步:添加配置

在各个服务模块里添加分布式事务的模式为AT:

seata:
  data-source-proxy-mode: AT

第二步:修改注释

在需要添加事务的方法上,将“@Transactional”注解修改注解为“@GlobalTransactional”

在这里插入图片描述

第三步:启动测试

断点打在判断库存数量是否大于请求数量这一行代码,查看数据库各表的状态

在这里插入图片描述

各个表的状态

在这里插入图片描述

放开断点,查看各张表的状态,可以看到,因为库存判断执行失败,请求数量大于库存数量,事务回滚,各张表回滚到初始状态,分布式事务问题得到解决。

在这里插入图片描述

小结

因为AT模式是先执行SQL语句,所以当多线程并发时,如果先执行了SQL语句,此时其他线程来操作数据库,就出现了数据脏读。使用AT模式,需要解决数据脏读问题。

Seata的解决方法是,引入全局锁,即对全局事务建立一个锁,分支事务操作完数据库,此时也不允许其他线程来操作数据,只有全局事务执行完毕后,才释放锁。

(断点时,加全局锁)

在这里插入图片描述

(放过断点,释放锁)

在这里插入图片描述

XA 模式

原理图

XA模式比AT模式结构清晰的多,就很简单,由事务协调者统一协调执行,一旦发现有分支事务执行失败,就回滚所有分支事务,如下:

(正常情况)
在这里插入图片描述

(异常情况)

在这里插入图片描述

第一步:修改配置

修改各模块的配置,模式改为XA,重启所有服务;

seata:
  registry:
  data-source-proxy-mode: XA

第二步:启动测试

同样,断点打在判断库存这一行代码,查看各张表的内容;

在这里插入图片描述

另外几张表情况,可以发现表的内容情况与XA实现描述是符合的

在这里插入图片描述

断点拿掉,程序报错;
在这里插入图片描述

数据未发现变化,XA模式同样解决了分布式事务问题;

在这里插入图片描述

小结

XA模式需锁定数据库资源,等待二阶段结束才释放,性能较差,但实现简单,不需要考虑数据脏读的问题。

总结

Seata可解决分布式事务问题,并提供了四种模式,AT为默认模式;

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Docker 命令(二)

查看 docker 版本信息 docker version #查看版本信息docker 信息查看 docker info Client:Context: defaultDebug Mode: falsePlugins:app: Docker App (Docker Inc., v0.9.1-beta3)buildx: Build with BuildKit (Docker Inc., v0.5.1-docker)Server:Containers: 0 …

Python补充笔记3-bug问题

目录 一、Bug 粗心导致的语法错误​ ​编辑 知识不熟练导致的错误​ 思路不清晰导致的问题​ 被动掉坑​ 二、try…except…else结构​ 三、try…except…else…finally结构​ 四、常见异常类型​编辑traceback模块 pycharm调试 一、Bug 粗心导致的语法错误 知识不熟练导致的…

【Vue 面试题10道】我好像之前想过要写,不过之前JavaScript面试题比较多,就暂时略过了,这些应该几乎把常问的都包括了

博主&#xff1a;_LJaXi Or 東方幻想郷 专栏&#xff1a; 前端面试题 开发工具&#xff1a;Vs Code 本题针对 Vue2 这些几乎把常用的都包括了&#xff0c;问别的就没意思了&#xff0c;毕竟工作拧螺丝嘛 我都好久不用Vue了&#xff0c;不过用了React再回看Vue感觉好简单啊… 其…

Dubbogo 详解

Dubbogo 详解 简介 dubbo功能很强大的微服务开发框架&#xff0c;支持多种通信协议&#xff0c;并具有流量治理的功能。 dubbo在有了大转变&#xff0c;拥抱了云原生&#xff0c;从哪些方面可以体现呢&#xff1f; 推出了自己的Trip协议修复了服务发现的级别&#xff0c;之…

20230723红米Redmi Note8Pro掉在水里的处理步骤

20230723红米Redmi Note8Pro掉在水里的处理步骤 2023/7/23 18:18 百度搜搜&#xff1a;小米手机进水 破音怎么处理 Redmi Note8Pro 6400万全场景四摄 液冷游戏芯 4500mAh长续航 NFC 18W快充 红外遥控 https://www.zhiliancy.com/a/q5podmr12.html 首页 / 热文 / 内容 小米喇叭…

【从删库到跑路】MySQL数据库的索引(一)——索引的结构(BTree B+Tree Hash),语法等

&#x1f38a;专栏【MySQL】 &#x1f354;喜欢的诗句&#xff1a;更喜岷山千里雪 三军过后尽开颜。 &#x1f386;音乐分享【如愿】 &#x1f970;欢迎并且感谢大家指出小吉的问题 文章目录 &#x1f354;概述&#x1f354;索引结构⭐B-Tree多路平衡查找树&#x1f3f3;️‍&a…

前端技术Vue学习笔记--001

前端技术Vue学习笔记 文章目录 前端技术Vue学习笔记1、Vue2和Vue3比较2、Vue简介3、Vue快速上手4、插值表达式{{}}5、Vue响应式特性6、Vue指令6.1、v-html指令6.2、v-show指令和v-if指令6.3、v-else指令和v-else-if指令6.4、v-on指令6.4.1、v-on指令基础6.4.2、v-on调用传参 6.…

win10电脑便签常驻桌面怎么设置?

你是否曾经因为繁忙的工作而忘记了一些重要的事项&#xff1f;相信很多人都会回答&#xff1a;忘记过&#xff01;其实在快节奏的职场中&#xff0c;我们经常需要记录一些重要的信息&#xff0c;例如会议时间、约见客户时间、今天需要完成的工作任务等。而为了能够方便地记录和…

阿里云安装宝塔面板

阿里云安装宝塔面板 1.安装步骤2.需要加入安全组&#xff0c;打开端口3.安装宝塔 1.安装步骤 1.这里主要以阿里云的服务器 ECS为例子,需要安装纯净的系统 创建过程: 这边先用的是免费的: 2.需要加入安全组&#xff0c;打开端口 进入实例选项卡&#xff1a; 快速添加&…

低代码平台协同OA升级,促进金融企业信息化建设

编者按&#xff1a;数字化办公是信息化时代每个企业不可避免的&#xff0c;OA系统是数字化办公的关键环节。如何与时俱进&#xff0c;保持企业的活力&#xff0c;增强企业综合竞争力&#xff1f;本文分析了企业OA系统为什么需要升级&#xff0c;并进一步指出如何实现升级。 关…

Linux环境下Elasticsearch相关软件安装

Linux环境下Elasticsearch相关软件安装 本文将介绍在linux(Centos7)环境下安装Elasticsearch相关的软件。 1、安装Elasticsearch 1.1 Elasticsearch下载 首先去Elasticsearch官网下载相应版本的安装包&#xff0c;下载之后传输到linux服务器上。 官网地址&#xff1a;http…

在自定义数据集上微调Alpaca和LLaMA

本文将介绍使用LoRa在本地机器上微调Alpaca和LLaMA&#xff0c;我们将介绍在特定数据集上对Alpaca LoRa进行微调的整个过程&#xff0c;本文将涵盖数据处理、模型训练和使用流行的自然语言处理库(如Transformers和hugs Face)进行评估。此外还将介绍如何使用grado应用程序部署和…

STM32MP157驱动开发——LED驱动(设备树)

文章目录 设备树驱动模型如何使用设备树写驱动程序设备树节点要与 platform_driver 能匹配设备树节点指定资源&#xff0c;platform_driver 获得资源 LED 模板驱动程序的改造&#xff1a;设备树驱动模型修改设备树&#xff0c;添加 led 设备节点修改 platform_driver 的源码编译…

设计模式再探——状态模式

目录 一、背景介绍二、思路&方案三、过程1.状态模式简介2.状态模式的类图3.状态模式代码4.状态模式还可以优化的地方5.状态模式的项目实战&#xff0c;优化后 四、总结五、升华 一、背景介绍 最近产品中有这样的业务需求&#xff0c;不同时间(这里不是活动的执行时间&…

前端学习——Vue (Day1)

Vue 快速上手 Vue 是什么 创建 Vue 实例 Vue2官网&#xff1a;https://v2.cn.vuejs.org/ <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge…

基于单片机的语音识别智能垃圾桶垃圾分类的设计与实现

功能介绍 以51单片机作为主控系统&#xff1b;液晶显示当前信息和状态&#xff1b;通过语音识别模块对当前垃圾种类进行语音识别&#xff1b; 通过蜂鸣器进行声光报警提醒垃圾桶已满&#xff1b;采用舵机控制垃圾桶打开关闭&#xff1b;超声波检测当前垃圾桶满溢程度&#xff1…

【目标跟踪】2、FairMOT | 平衡多目标跟踪中的目标检测和 Re-ID 任务 | IJCV2021

文章目录 一、背景二、方法2.1 Backbone2.2 检测分支2.3 Re-ID 分支2.4 训练 FairMOT2.5 Online Inference 三、效果3.1 数据集3.2 实现细节3.3 消融实验3.4 最终效果 论文&#xff1a;FairMOT: On the Fairness of Detection and Re-Identification in Multiple Object Tracki…

大模型开发(十):Chat Completion Models API 详解

全文共8000余字&#xff0c;预计阅读时间约18~28分钟 | 满满干货(附代码案例)&#xff0c;建议收藏&#xff01; 本文目标&#xff1a;详解Chat Completion Models的参数及应用实例&#xff0c;并基于该API实现一个本地知识库的多轮对话智能助理 代码&文件下载点这里 一、…

【前端|CSS系列第4篇】CSS布局之网格布局

前言 最近在做的一个项目前台首页有一个展示词条的功能&#xff0c;每一个词条都以一个固定大小的词条卡片进行展示&#xff0c;要将所有的词条卡片展示出来&#xff0c;大概是下面这种布局 每一行的卡片数目会随着屏幕大小自动变化&#xff0c;并且希望整个卡片区域周围不要…

ChatGPT 4.0 —— Code Interpreter

&#x1f4ce;产品销售数据集.csv 选取以上的数据集作为输入&#xff0c;对Code Interpreter 进行测试 1.输入指定数据集&#xff0c;要求给出该数据集的概貌 2.请分析销售的总金额和其他变量的关系 Python Script: # Import required libraries import matplotlib.pyplot a…