微服务事务管理(Dubbo)

Seata 是什么

Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。

一、示例架构说明

可在此查看本示例完整代码地址:dubbo-samples-seata

用户采购商品业务,整个业务包含3个微服务:

  • 库存服务: 扣减给定商品的库存数量。
  • 订单服务: 根据采购请求生成订单。
  • 账户服务: 用户账户金额扣减。

image.png

StorageService

public interface StorageService {

    /**
     * 扣除存储数量
     */
    void deduct(String commodityCode, int count);
}

OrderService

public interface OrderService {

    /**
     * 创建订单
     */
    Order create(String userId, String commodityCode, int orderCount);
}

AccountService

public interface AccountService {

    /**
     * 从用户账户中借出
     */
    void debit(String userId, int money);
}

二、主要的业务逻辑

BusinessService

public class BusinessServiceImpl implements BusinessService {

    private StorageService storageService;

    private OrderService orderService;

    /**
     * 采购
     */
    public void purchase(String userId, String commodityCode, int orderCount) {
        // 扣除存储数量
        storageService.deduct(commodityCode, orderCount);
        // 创建订单
        orderService.create(userId, commodityCode, orderCount);
    }
}

StorageService

public class StorageServiceImpl implements StorageService {

    private JdbcTemplate jdbcTemplate;
  
    @Override
    public void deduct(String commodityCode, int count) {
        // 修改数据库:扣减存储数量
        jdbcTemplate.update("update storage_tbl set count = count - ? where commodity_code = ?",
                new Object[]{count, commodityCode});
    }
}

OrderService

public class OrderServiceImpl implements OrderService {

    private AccountService accountService;
    
    private JdbcTemplate jdbcTemplate;

    public Order create(String userId, String commodityCode, int orderCount) {
        // 计算金额
        int orderMoney = calculate(commodityCode, orderCount);

        // 用户账户中扣减金额
        accountService.debit(userId, orderMoney);

        // 修改数据库:新建订单
        final Order order = new Order();
        order.userId = userId;
        order.commodityCode = commodityCode;
        order.count = orderCount;
        order.money = orderMoney;
        KeyHolder keyHolder = new GeneratedKeyHolder();
        jdbcTemplate.update(con -> {
            PreparedStatement pst = con.prepareStatement(
                    "insert into order_tbl (user_id, commodity_code, count, money) values (?, ?, ?, ?)",
                    PreparedStatement.RETURN_GENERATED_KEYS);
            pst.setObject(1, order.userId);
            pst.setObject(2, order.commodityCode);
            pst.setObject(3, order.count);
            pst.setObject(4, order.money);
            return pst;
        }, keyHolder);
        order.id = keyHolder.getKey().longValue();
        return order;
    }
}

AccountService

public class AccountServiceImpl implements AccountService {
        
    private JdbcTemplate jdbcTemplate;
    
    @Override
    public void debit(String userId, int money) {  
        // 修改数据库:用户账户中扣减金额      
        jdbcTemplate.update("update account_tbl set money = money - ? where user_id = ?", new Object[]{money, userId});
    }
}

三、快速启动示例

Step 1: 下载源码

git clone -b master https://github.com/apache/dubbo-samples.git
cd ./dubbo-samples-transaction/

Step 2: 通过 docker-compose 启动 Seata-Server 和 MySQL 等

在此示例中,我们使用 docker-compose 快速拉起 seata-server 和 mysql 等服务。

cd src/main/resources/docker
docker-compose up

Step 3: 构建用例

执行 maven 命令,打包 demo 工程

mvn clean package

Step 4: 启动 AccountService

java -classpath ./target/dubbo-samples-transaction-1.0-SNAPSHOT.jar org.apache.dubbo.samples.starter.DubboAccountServiceStarter

Step 5: 启动 OrderService

java -classpath ./target/dubbo-samples-transaction-1.0-SNAPSHOT.jar org.apache.dubbo.samples.starter.DubboOrderServiceStarter

Step 6: 启动 StorageService

java -classpath ./target/dubbo-samples-transaction-1.0-SNAPSHOT.jar org.apache.dubbo.samples.starter.DubboStorageServiceStarter

Step 7: 启动 BusinessService

java -classpath ./target/dubbo-samples-transaction-1.0-SNAPSHOT.jar org.apache.dubbo.samples.starter.DubboBusinessTester

四、示例核心流程

 

image.png

Step 1: 修改业务代码

此处仅仅需要一行注解 @GlobalTransactional 写在业务发起方的方法上:

    @GlobalTransactional
    public void purchase(String userId, String commodityCode, int orderCount) {
        ......
    }

Step 2: 安装数据库

  • 要求: MySQL (InnoDB 存储引擎)。

提示: 事实上例子中3个微服务需要3个独立的数据库,但为了方便我们使用同一物理库并配置3个逻辑连接串。

更改以下xml文件中的数据库url、username和password

dubbo-account-service.xml dubbo-order-service.xml dubbo-storage-service.xml

    <property name="url" value="jdbc:mysql://x.x.x.x:3306/xxx" />
    <property name="username" value="xxx" />
    <property name="password" value="xxx" />

Step 3: 为 Seata 创建 undo_log 表

UNDO_LOG 此表用于 Seata 的AT模式。

-- 注意当 Seata 版本升级至 0.3.0+ 将由之前的普通索引变更为唯一索引。
CREATE TABLE `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,
  `ext` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

Step 4: 创建相关业务表


DROP TABLE IF EXISTS `storage_tbl`;
CREATE TABLE `storage_tbl` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `commodity_code` varchar(255) DEFAULT NULL,
  `count` int(11) DEFAULT 0,
  PRIMARY KEY (`id`),
  UNIQUE KEY (`commodity_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


DROP TABLE IF EXISTS `order_tbl`;
CREATE TABLE `order_tbl` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` varchar(255) DEFAULT NULL,
  `commodity_code` varchar(255) DEFAULT NULL,
  `count` int(11) DEFAULT 0,
  `money` int(11) DEFAULT 0,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


DROP TABLE IF EXISTS `account_tbl`;
CREATE TABLE `account_tbl` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` varchar(255) DEFAULT NULL,
  `money` int(11) DEFAULT 0,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Step 5: 启动 Seata-Server 服务

  • 下载服务器软件包,将其解压缩。
Usage: sh seata-server.sh(for linux and mac) or cmd seata-server.bat(for windows) [options]
  Options:
    --host, -h
      The host to bind.
      Default: 0.0.0.0
    --port, -p
      The port to listen.
      Default: 8091
    --storeMode, -m
      log store mode : file、db
      Default: file
    --help

e.g.

sh seata-server.sh -p 8091 -h 127.0.0.1 -m file

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

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

相关文章

88. 合并两个有序数组

题目链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 解题思路&#xff1a; 因为num1只有前m个元素是有效元素&#xff0c;num1和num2有序&#xff0c;所以可以使用双指针进行比较&#xff0c;另外还可以利用num1后半部分可以使用的这…

五子棋游戏禁手算法的改进

五子棋游戏禁手算法的改进 五子棋最新的禁手规则&#xff1a; 1&#xff0e;黑棋禁手判负、白棋无禁手。黑棋禁手有“三三”&#xff08;包括“四三三”&#xff09;、“四四”&#xff08;包括“四四三”&#xff09;和“长连”。黑棋只能以“四三”取胜。 2&#xff0e;黑方…

Vue框架--理解MVVM

我们知道&#xff0c;MVVM是Model-View-ViewModel的简写。它本质上就是MVC的改进版。我们看看MVVM的模型架构&#xff0c;如下所示: 架构理解与实例

基于Matlab实现生活中的图像信号分类(附上源码+数据集)

在我们的日常生活中&#xff0c;我们经常会遇到各种各样的图像信号&#xff0c;例如照片、视频、图标等等。对这些图像信号进行分类和识别对于我们来说是非常有用的。在本文中&#xff0c;我将介绍如何使用Matlab来实现生活中的图像信号分类。 文章目录 介绍源码数据集下载 介…

合宙Air724UG LuatOS-Air LVGL API控件--图表 (Chart)

图表 (Chart) 一幅图胜过一千个字&#xff0c;通过图表展示出的数据内容能让用户更快速有效的了解数据特征。 代码示例 – 创建图表 chart lvgl.chart_create(lvgl.scr_act(), nil) lvgl.obj_set_size(chart, 200, 150) lvgl.obj_align(chart, nil, lvgl.ALIGN_CENTER, 0, …

Fiddler Response私人订制

在客户端接口的测试中&#xff0c;我们经常会需要模拟各种返回状态或者特定的返回值&#xff0c;常见的是用Fiddler模拟各种请求返回值场景&#xff0c;如重定向AutoResponder、请求拦截修改再下发等等。小编在近期的测试中遇到的一些特殊的请求返回模拟的测试场景&#xff0c;…

Opencv-C++笔记 (18) : 轮廓和凸包

文章目录 一、轮廓findContours发现轮廓drawContours绘制轮廓代码 二.几何及特性概括——凸包(Convex Hull)凸包概念凸包扫描算法介绍——Graham扫描算法 相关API介绍程序示例轮廓集合及特性性概括——轮廓周围绘制矩形框和圆形相关理论介绍轮廓周围绘制矩形 -API绘制步骤程序实…

一台服务器上部署 Redis 伪集群

哈喽大家好&#xff0c;我是咸鱼 今天这篇文章介绍如何在一台服务器&#xff08;以 CentOS 7.9 为例&#xff09;上通过 redis-trib.rb 工具搭建 Redis cluster &#xff08;三主三从&#xff09; redis-trib.rb 是一个基于 Ruby 编写的脚本&#xff0c;其功能涵盖了创建、管…

ExpressLRS开源之接收机固件编译烧录步骤

ExpressLRS开源之接收机固件编译烧录步骤 1. 源由2. 编译步骤2.1 推荐源代码指定方案2.2 方法一&#xff1a;ELRS Configurator步骤一&#xff1a;下载ELRS Configurator工具步骤二&#xff1a;安装ELRS Configurator工具步骤三&#xff1a;使用ELRS Configurator工具进行配置步…

3D点云处理:获取最高层范围内的点(附源码)

文章目录 0. 测试效果1. 基本内容2. 代码实现文章目录:3D视觉个人学习目录微信: dhlddxB站: Non-Stop_目标:仅获取最高层范围内的点云用于后续处理0. 测试效果 红色为提取的最高层范围内的点云 1. 基本内容 要获取点云中特定高度范围内的点云,可以使用高度条件过滤的原理。…

Docker技术--Docker简介和架构

1.Docker简介 (1).引入 我们之前学习了EXSI&#xff0c;对于虚拟化技术有所了解&#xff0c;但是我们发现类似于EXSI这样比较传统的虚拟化技术是存在着一定的缺陷:所占用的资源比较多&#xff0c;简单的说&#xff0c;就是你需要给每一个用户提供一个操作平台&#xff0c;这一个…

【数据结构】 二叉树面试题讲解->贰

文章目录 &#x1f30f;引言&#x1f384;[二叉树遍历](https://www.nowcoder.com/practice/4b91205483694f449f94c179883c1fef?tpId60&&tqId29483&rp1&ru/activity/oj&qru/ta/tsing-kaoyan/question-ranking)&#x1f431;‍&#x1f464;题目描述&#…

【Flutter】下载安装Flutter并使用学习dart语言

前言 安装flutter, 并使用flutter内置的dartSDK学习使用dart语言。 编辑器&#xff1a; Android Studio fluuter 版本 : flutter_windows_3.13.1 内置dartSDK : 3.1.0 dart路径路径&#xff1a; flutter安装路径\bin\cache\dart-sdk 安装Flutter 下载安装包 flutter下载地址…

智慧工地源码 智慧大屏、手机APP、SaaS模式

一、智慧工地可以通过安全八要素来提升安全保障&#xff0c;具体措施包括&#xff1a; 1.安全管理制度&#xff1a;建立科学完善的安全管理制度&#xff0c;包括安全标准规范、安全生产手册等&#xff0c;明确各项安全管理职责和要求。 2.安全培训教育&#xff1a;对工地人…

MySQL数据库——多表查询(3)-自连接、联合查询、子查询

目录 自连接 查询语法 自连接演示 联合查询 查询语法 子查询 介绍 标量子查询 列子查询 行子查询 表子查询 自连接 通过前面的学习&#xff0c;我们对于连接已经有了一定的理解。而自连接&#xff0c;通俗地去理解就是自己连接自己&#xff0c;即一张表查询多次。…

Qt/C++编写视频监控系统81-Onvif报警抓图和录像并回放

一、前言 视频监控系统中的图文警情模块&#xff0c;是通过Onvif协议的事件订阅拿到的&#xff0c;通过事件订阅后&#xff0c;设备的各种报警事件比如入侵报警/遮挡报警/越界报警/开关量报警等&#xff0c;触发后都会主动往订阅者发送&#xff0c;而且一般都是会发送两次&…

【C++】C++11新特性(下)

上篇文章&#xff08;C11的新特性&#xff08;上&#xff09;&#xff09;我们讲述了C11中的部分重要特性。本篇接着上篇文章进行讲解。本篇文章主要进行讲解&#xff1a;完美转发、新类的功能、可变参数模板、lambda 表达式、包装器。希望本篇文章会对你有所帮助。 文章目录 一…

Git和Github的基本用法

目录 背景 下载安装 安装 git for windows 安装 tortoise git 使用 Github 创建项目 注册账号 创建项目 下载项目到本地 Git 操作的三板斧 放入代码 三板斧第一招: git add 三板斧第二招: git commit 三板斧第三招: git push 小结 &#x1f388;个人主页&#xf…

多源最短路径算法:Floyd-Warshall算法分析

文章目录 图的邻接矩阵 一.Floyd-Warshall算法思想(基于动态规划)二.Floyd-Warshall算法接口笔记附录:单源最短路径--Bellman-Ford算法1.Bellman-Ford算法接口核心部分2.Bellman-Ford算法接口 图的邻接矩阵 namespace Graph_Structure {//Vertex是代表顶点的数据类型,Weight是…

开发智能应用的新范式:大数据、AI和云原生如何构建智能软件

文章目录 1.利用大数据实现智能洞察2. 集成人工智能和机器学习3. 云原生架构的弹性和灵活性4. 实现实时处理和响应5. 数据安全和隐私保护6. 可解释性和透明性7. 持续创新和迭代8. 数据伦理和合规性 &#x1f388;个人主页&#xff1a;程序员 小侯 &#x1f390;CSDN新晋作者 &a…