若依微服务实现分布式事务

news2024/9/24 1:27:32

一、基本介绍

1、什么是分布式事务

指一次大的操作由不同的小操作组成的,这些小的操作分布在不同的服务器上,分布式事务需要保证这些小操作要么全部成功,要么全部失败。从本质上来说,分布式事务就是为了保证不同数据库的数据一致性。

2、为什么要使用分布式事务

在微服务独立数据源的思想,每一个微服务都有一个或者多个数据源,虽然单机单库事务已经非常成熟,但是由于网路延迟和不可靠的客观因素,分布式事务到现在也还没有成熟的方案,对于中大型网站,特别是涉及到交易的网站,一旦将服务拆分微服务,分布式事务一定是绕不开的一个组件,通常解决分布式事务问题。

3、seata 分布式事务

Seata是阿里开源的一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。

Seata目标打造一站式的分布事务的解决方案,最终会提供四种事务模式:

  • AT 模式:参见(《Seata AT 模式》 https://seata.io/zh-cn/docs/dev/mode/at-mode.html)文档

  • TCC 模式:参见(《Seata TCC 模式》 https://seata.io/zh-cn/docs/dev/mode/tcc-mode.html)文档

  • Saga 模式:参见(《SEATA Saga 模式》 https://seata.io/zh-cn/docs/dev/mode/at-mode.html)文档

  • XA 模式:正在开发中...

目前使用的流行度情况是:AT > TCC > Saga。因此,我们在学习Seata的时候,可以花更多精力在AT模式上,最好搞懂背后的实现原理,毕竟分布式事务涉及到数据的正确性,出问题需要快速排查定位并解决。

二、下载方式

  • Windows平台安装包下载
    可以从https://github.com/seata/seata/releases下载seata-server-$version.zip

Windows下载解压后(.zip),直接点击bin/seata-server.bat就可以了。(本文使用1.4.0版本)

三、如何使用

1、创建相关测试数据库和表

# 订单数据库信息 seata_order
DROP DATABASE IF EXISTS seata_order;
CREATE DATABASE seata_order;

DROP TABLE IF EXISTS seata_order.p_order;
CREATE TABLE seata_order.p_order
(
    id               INT(11) NOT NULL AUTO_INCREMENT,
    user_id          INT(11) DEFAULT NULL,
    product_id       INT(11) DEFAULT NULL,
    amount           INT(11) DEFAULT NULL,
    total_price      DOUBLE       DEFAULT NULL,
    status           VARCHAR(100) DEFAULT NULL,
    add_time         DATETIME     DEFAULT CURRENT_TIMESTAMP,
    last_update_time DATETIME     DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (id)
) ENGINE = InnoDB
  AUTO_INCREMENT = 1
  DEFAULT CHARSET = utf8mb4;

DROP TABLE IF EXISTS seata_order.undo_log;
CREATE TABLE seata_order.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 = utf8mb4;
  
# 产品数据库信息 seata_product
DROP DATABASE IF EXISTS seata_product;
CREATE DATABASE seata_product;

DROP TABLE IF EXISTS seata_product.product;
CREATE TABLE seata_product.product
(
    id               INT(11) NOT NULL AUTO_INCREMENT,
    price            DOUBLE   DEFAULT NULL,
    stock            INT(11) DEFAULT NULL,
    last_update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (id)
) ENGINE = InnoDB
  AUTO_INCREMENT = 1
  DEFAULT CHARSET = utf8mb4;

DROP TABLE IF EXISTS seata_product.undo_log;
CREATE TABLE seata_product.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 = utf8mb4;

INSERT INTO seata_product.product (id, price, stock)
VALUES (1, 10, 20);


# 账户数据库信息 seata_account
DROP DATABASE IF EXISTS seata_account;
CREATE DATABASE seata_account;

DROP TABLE IF EXISTS seata_account.account;
CREATE TABLE seata_account.account
(
    id               INT(11) NOT NULL AUTO_INCREMENT,
    balance          DOUBLE   DEFAULT NULL,
    last_update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (id)
) ENGINE = InnoDB
  AUTO_INCREMENT = 1
  DEFAULT CHARSET = utf8mb4;

DROP TABLE IF EXISTS seata_account.undo_log;
CREATE TABLE seata_account.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 = utf8mb4;
INSERT INTO seata_account.account (id, balance)
VALUES (1, 50);

其中,每个库中的undo_log表,是Seata AT模式必须创建的表,主要用于分支事务的回滚。
另外,为了测试方便,插入了一条id = 1account记录,和一条id = 1product记录。

2、引入ruoyi-common-datasource依赖(包含seata配置)

<!-- ruoyi common datasource -->
<dependency>
	<groupId>com.ruoyi</groupId>
	<artifactId>ruoyi-common-datasource</artifactId>
</dependency>

3、服务配置文件

# spring配置
spring: 
  redis:
    host: localhost
    port: 6379
    password: 
  datasource:
    druid:
      stat-view-servlet:
        enabled: true
        loginUsername: admin
        loginPassword: 123456
    dynamic:
      druid:
        initial-size: 5
        min-idle: 5
        maxActive: 20
        maxWait: 60000
        timeBetweenEvictionRunsMillis: 60000
        minEvictableIdleTimeMillis: 300000
        validationQuery: SELECT 1 FROM DUAL
        testWhileIdle: true
        testOnBorrow: false
        testOnReturn: false
        poolPreparedStatements: true
        maxPoolPreparedStatementPerConnectionSize: 20
        filters: stat,wall,slf4j
        connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
      datasource:
          # 主库数据源
          master:
            driver-class-name: com.mysql.cj.jdbc.Driver
            url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
            username: root
            password: password
          # seata_order数据源
          order:
            username: root
            password: password
            url: jdbc:mysql://localhost:3306/seata_order?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
            driver-class-name: com.mysql.cj.jdbc.Driver
          # seata_account数据源
          account:
            username: root
            password: password
            url: jdbc:mysql://localhost:3306/seata_account?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
            driver-class-name: com.mysql.cj.jdbc.Driver
          # seata_product数据源
          product:
            username: root
            password: password
            url: jdbc:mysql://localhost:3306/seata_product?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
            driver-class-name: com.mysql.cj.jdbc.Driver
      seata: true    #开启seata代理,开启后默认每个数据源都代理,如果某个不需要代理可单独关闭

# seata配置
seata:
  enabled: true
  # Seata 应用编号,默认为 ${spring.application.name}
  application-id: ${spring.application.name}
  # Seata 事务组编号,用于 TC 集群名
  tx-service-group: ${spring.application.name}-group
  # 关闭自动代理
  enable-auto-data-source-proxy: false
  # 服务配置项
  service:
    # 虚拟组和分组的映射
    vgroup-mapping:
      ruoyi-system-group: default
    # 分组和 Seata 服务的映射
    grouplist:
      default: 127.0.0.1:8091
  config:
    type: file
  registry:
    type: file

# mybatis配置
mybatis:
    # 搜索指定包别名
    typeAliasesPackage: com.ruoyi.system
    # 配置mapper的扫描,找到所有的mapper.xml映射文件
    mapperLocations: classpath:mapper/**/*.xml

# swagger配置
swagger:
  title: 系统模块接口文档
  license: Powered By ruoyi
  licenseUrl: https://ruoyi.vip

注意:
一定要设置spring.datasource.dynamic.seata配置项为true,开启对Seata的集成,否则会导致Seata全局事务回滚失败。

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

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

相关文章

2.1 数据类型-常量-变量(整型-浮点-字符)

目录 1 数据类型 1.1 关键字 2 常量 3 变量 3.1 命名规则 4 整形数据 4.1 符号常量 4.2 整型变量 5 浮点型数据 5.1 浮点型常量 5.2 浮点型变量 6 字符型数据 6.1 字符型常量 转义字符 6.2 字符数据在内存中的存储形式及其使用方法 6.3 ASCII码表 7 字符串型常…

homebrew安装mysql的一些问题

本文目录 一、Homebrew镜像安装二、mac安装mysql2.1、修改mysql密码 本文基于mac环境下进行的安装 一、Homebrew镜像安装 Homebrew国内如何自动安装&#xff0c;运行命令/bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)" 会…

2024年,游戏行业还值得进入吗?

来自知乎问题“2024年&#xff0c;游戏行业还值得进入吗&#xff1f;”的回答。 ——原问题描述&#xff1a;从超小厂执行策划做起&#xff0c;未来有前途吗&#xff1f; 展望2024年&#xff0c;国内外的游戏市场环境或将变得更加复杂&#xff0c;曾经那个水大鱼大的时代过去了…

ArduPilot开源飞控之MAVProxy深入研读系列 - 2蜂群链路

ArduPilot开源飞控之MAVProxy深入研读系列 - 2蜂群链路 1. 源由2. 蜂群链路2.1 拓扑结构2.2 设备标识2.3 命令列表 3. 蜂群应用4. 总结技术进步未来挑战 5. 参考资料 1. 源由 MAVProxy的一个关键功能是它能够通过UDP将来自无人机的消息转发到网络上的多个其他设备上的地面站软…

AI绘画图生图有什么用?

随着AI渗透到我们生活中的各个角落&#xff0c;AI绘画图生图的出现&#xff0c;更是在艺术领域引起了广泛的关注和讨论。那么&#xff0c;AI绘画图生图究竟有什么作用呢? 首先&#xff0c;AI绘画图生图能够极大地提高创作效率。传统的绘画过程需要艺术家们花费大量的时间和精力…

uni-app实现页面之间的跳转传参(八)

界面之间的参数传递在 开发中经常会用到,这节主要将一下uni-app开发应用是的传参情况。如下图所示,我的一级界面将点检分成三类:日点检、周点检和年保养;在点击相应的会导航到相应的功能。 在uni-app中常用的方法有uni.navigateTo(OBJECT)、uni.redirectTo(OBJECT);简单的…

一文带你学会如何部署个人博客到云服务器,并进行域名备案与解析!

哈喽&#xff0c;大家好呀&#xff01;这里是码农后端。之前我给大家介绍了如何快速注册一个自己的域名&#xff0c;并创建一台自己的阿里云ECS云服务器。本篇将介绍如何将个人博客部署到云服务器&#xff0c;并进行域名备案与解析。 1、域名备案 注册了域名并购买了云服务器之…

牛客循环5.27

1006 错误代码 不知道原因&#xff0c;有大佬解答一下吗 ac代码 1007 错误代码 ac代码

AI音乐神器Suno V3.5进化全解析:功能升级吊炸天,让音乐创作更简单!

前言 目前&#xff0c;suno的v3.5版本已经向Pro和Premier会员开放&#xff0c;从更新当天到现在我已经使用了近2000积分&#xff0c;接下来我将v3.5的使用体验和与旧版本v3进行比较&#xff0c;让大家更直观的感受到v3.5的强大。 其中一个最屌的功能&#xff0c;我放在最后介绍…

linux下cp和mv命令显示进度条

1.查看当前系统下coreutils工具包的版本号&#xff1a; [rootk8s-master ~]# rpm -qa | grep -w coreutils coreutils-8.22-24.el7_9.2.x86_64当前版本为8.22。 因为cp 和 mv 命令由 coreutils 软件包提供&#xff0c;所以需要重新下载 coreutils 软件包配置补丁 2.下载core…

创意学习剪辑利器:一键添加动图水印,轻松提升视频专业度与创意新境界!

在数字化时代&#xff0c;视频已成为我们生活中不可或缺的一部分。无论是学习分享、工作展示还是生活记录&#xff0c;视频都以其直观、生动的形式&#xff0c;赢得了广大用户的喜爱。然而&#xff0c;如何在众多的视频中脱颖而出&#xff0c;展现出自己的专业度和创意&#xf…

CI/CD:持续集成/持续部署

1. 安装docker、docker-compose # 安装Docker yum install -y yum-utils device-mapper-persistent-data lvm2 yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo sed -i sdownload.docker.commirrors.aliyun.com/docker-ce /…

【AD21】原理图PDF文件的输出

原理图PDF文件可以共享给团队成员&#xff0c;用于设计审核、讨论和协同工作。 菜单栏中点击文件->智能PDF。 在弹出的界面点击Next&#xff0c;勾选当前项目&#xff0c;修改文件名&#xff0c;避免与制造装备图PDF文件重名将其覆盖&#xff0c;点击Next。 只输出原理图…

谷歌AI搜索功能“翻车”,用户体验引担忧

近期&#xff0c;谷歌对其搜索引擎进行重大更新&#xff0c;推出了全新AI搜索功能“AI Overview”&#xff0c;试图通过人工智能技术提供更智能便捷的搜索体验&#xff0c;并追赶微软和OpenAI等竞争对手。然而事与愿违&#xff0c;这项备受期待的功能上线后却频频出错&#xff…

实现一个自定义 hook,用于强制刷新当前组件

写在前面 在 react 中&#xff0c;如果 state 数据发生变化&#xff0c;我们知道&#xff0c;会重新渲染该组件。 但是这个前提是我们需要依赖 state 数据的变化&#xff0c;那比如我们并不想定义 state&#xff0c;又或者说我们的操作不能引起 state 的变化&#xff0c;此时…

如何把学浪的视频保存到手机

你是不是还在为无法将学浪的视频保存到手机而烦恼&#xff1f;别担心&#xff0c;接下来我将为大家分享一个非常实用的方法&#xff0c;让你轻松实现这一目标&#xff01; 下载学浪的工具我已经打包好了&#xff0c;有需要的自己下载一下 学浪下载工具打包链接&#xff1a;百…

【408真题】2009-18

“接”是针对题目进行必要的分析&#xff0c;比较简略&#xff1b; “化”是对题目中所涉及到的知识点进行详细解释&#xff1b; “发”是对此题型的解题套路总结&#xff0c;并结合历年真题或者典型例题进行运用。 涉及到的知识全部来源于王道各科教材&#xff08;2025版&…

为什么我们会固执己见、为什么我们总认为自己是对的?

人为什么固执己见&#xff0c;是其所是&#xff0c;而非其所非&#xff1f;我们要有什么样的思维模式才能使自己有良好的判断力&#xff0c;才能作出恰当的预测和良好的决定呢&#xff1f;作者Julia Galef对TED发表演讲时提出自己的观点。以下是演讲的文字实录。 我想让你们想象…

刷代码随想录有感(80):回溯算法——解数独

题干&#xff1a; 代码&#xff1a; class Solution { public:bool backtracking(vector<vector<char>>& board){for(int i 0; i < board.size(); i){for(int j 0; j < board[0].size(); j){if(board[i][j] .){for(char k 1; k < 9; k){if(isval…

前缀和算法专题

应用: 计算数组中某区间的和 一. 一维前缀和[模版] 答案 二. 二维前缀和[模版] 答案 三. 寻找数组的中心下标 答案 四. 除自身以外数组的乘积 答案 五. 和为k的子数组 答案 六. 和可被k整除的子数组 答案 七. 连续数组 答案 八. 矩阵区域和 答案