Apache Seata Mac下的Seata Demo环境搭建

本文来自 Apache Seata官方文档,欢迎访问官网,查看更多深度文章。
本文来自 Apache Seata官方文档,欢迎访问官网,查看更多深度文章。

Mac下的Seata Demo环境搭建(AT模式)

前言

最近因为工作需要,研究学习了Seata分布式事务框架,本文把自己学习的知识记录一下

Seata总览

cloc代码统计

先看一下seata项目cloc代码统计(截止到2020-07-20)

在这里插入图片描述

Java代码行数大约是 97K

代码质量

单元测试覆盖率50%

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Demo代码

本文讲的Demo代码是seata-samples项目下的seata-samples-dubbo模块,地址如下:

https://github.com/apache/incubator-seata-samples/tree/master/dubbo

解决的核心问题

AT模式的Demo例子给出了一个典型的分布式事务场景:

  • 在一个采购交易中,需要:
  1. 扣减商品库存
  2. 扣减用户账号余额
  3. 生成采购订单
  • 很明显,以上3个步骤必须:要么全部成功,要么全部失败,否则系统的数据会错乱
  • 而现在流行的微服务架构,一般来说,库存,账号余额,订单是3个独立的系统
  • 每个微服务有自己的数据库,相互独立

这里就是分布式事务的场景。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

解决方案

AT模式解决这个问题的思路其实很简单,一句话概括就是:

在分布式事务过程中,记录待修改的数据修改前和修改后的值到undo_log表,万一交易中出现异常,通过这个里的数据做回滚

当然,具体代码实现起来,我相信很多细节远没这么简单。

Demo代码结构

从github上clone最新的代码

git clone git@github.com:apache/incubator-seata-samples.git

阅读Demo代码结构

$ cd seata-samples/dubbo/
$ tree -C  -I 'target' .
.
├── README.md
├── pom.xml
├── seata-samples-dubbo.iml
└── src
    └── main
        ├── java
        │   └── io
        │       └── seata
        │           └── samples
        │               └── dubbo
        │                   ├── ApplicationKeeper.java
        │                   ├── Order.java
        │                   ├── service
        │                   │   ├── AccountService.java
        │                   │   ├── BusinessService.java
        │                   │   ├── OrderService.java
        │                   │   ├── StorageService.java
        │                   │   └── impl
        │                   │       ├── AccountServiceImpl.java
        │                   │       ├── BusinessServiceImpl.java
        │                   │       ├── OrderServiceImpl.java
        │                   │       └── StorageServiceImpl.java
        │                   └── starter
        │                       ├── DubboAccountServiceStarter.java
        │                       ├── DubboBusinessTester.java
        │                       ├── DubboOrderServiceStarter.java
        │                       └── DubboStorageServiceStarter.java
        └── resources
            ├── file.conf
            ├── jdbc.properties
            ├── log4j.properties
            ├── registry.conf
            ├── spring
            │   ├── dubbo-account-service.xml
            │   ├── dubbo-business.xml
            │   ├── dubbo-order-service.xml
            │   └── dubbo-storage-service.xml
            └── sql
                ├── dubbo_biz.sql
                └── undo_log.sql

13 directories, 27 files
  • 在io.seata.samples.dubbo.starter包下的4个*Starter类,分别模拟上面所述的4个微服务

    • Account
    • Business
    • Order
    • Storage
  • 4个服务都是标准的dubbo服务,配置文件在seata-samples/dubbo/src/main/resources/spring目录下

  • 运行demo需要把这4个服务都启动起来,Business最后启动

  • 主要的逻辑在io.seata.samples.dubbo.service,4个实现类分别对应4个微服务的业务逻辑

  • 数据库信息的配置文件:src/main/resources/jdbc.properties

时序图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Ok, 赶紧动手, Make It Happen!

运行Demo

MySQL

建表

执行seata-samples/dubbo/src/main/resources/sql的脚本dubbo_biz.sql和undo_log.sql

mysql> show tables;
+-----------------+
| Tables_in_seata |
+-----------------+
| account_tbl     |
| order_tbl       |
| storage_tbl     |
| undo_log        |
+-----------------+
4 rows in set (0.01 sec)

执行完之后,数据库里应该有4个表

修改seata-samples/dubbo/src/main/resources/jdbc.properties文件

根据你MySQL运行的环境修改变量的值

jdbc.account.url=jdbc:mysql://localhost:3306/seata
jdbc.account.username=your_username
jdbc.account.password=your_password
jdbc.account.driver=com.mysql.jdbc.Driver
# storage db config
jdbc.storage.url=jdbc:mysql://localhost:3306/seata
jdbc.storage.username=your_username
jdbc.storage.password=your_password
jdbc.storage.driver=com.mysql.jdbc.Driver
# order db config
jdbc.order.url=jdbc:mysql://localhost:3306/seata
jdbc.order.username=your_username
jdbc.order.password=your_password
jdbc.order.driver=com.mysql.jdbc.Driver

ZooKeeper

启动ZooKeeper,我的本地的Mac是使用Homebrew安装启动的

$ brew services start zookeeper 
==> Successfully started `zookeeper` (label: homebrew.m

$ brew services list           
Name              Status  User    Plist
docker-machine    stopped         
elasticsearch     stopped         
kafka             stopped         
kibana            stopped         
mysql             started portman /Users/portman/Librar
y/LaunchAgents/homebrew.mxcl.mysql.plist
nginx             stopped         
postgresql        stopped         
redis             stopped         
zookeeper         started portman /Users/portman/Librar
y/LaunchAgents/homebrew.mxcl.zookeeper.plist

启动TC事务协调器

在这个链接里页面中,下载对应版本的seata-server程序,我本地下载的是1.2.0版本

  1. 进入文件所在目录并解压文件
  2. 进入seata目录
  3. 执行启动脚本
$ tar -zxvf seata-server-1.2.0.tar.gz
$ cd seata
$ bin/seata-server.sh

观察启动日志是否有报错信息,如果一切正常,并看到了以下的Server started的信息,说明启动成功了。

2020-07-23 13:45:13.810 INFO [main]io.seata.core.rpc.netty.RpcServerBootstrap.start:155 -Server started ...

IDE中启动模拟的微服务

  1. 首先要把seata-samples项目导入到本地IDE中,这里我用的是IntelliJ IDEA
  2. 刷新Maven的工程依赖
  3. 先启动Account,Order,Storage这个3个服务,然后Business才能去调用,对应的启动类分别是:
io.seata.samples.dubbo.starter.DubboStorageServiceStarter
io.seata.samples.dubbo.starter.DubboOrderServiceStarter
io.seata.samples.dubbo.starter.DubboStorageServiceStarter

每个服务启动完之后,看到这句提示信息,说明服务启动成功了

Application is keep running ...

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

启动成功后,account_tbl,storage_tbl表会有两条初始化的数据,分别是账户余额和商品库存

mysql> SELECT * FROM account_tbl; SELECT * FROM storage_tbl;
+----+---------+-------+
| id | user_id | money |
+----+---------+-------+
|  1 | U100001 |   999 |
+----+---------+-------+
1 row in set (0.00 sec)

+----+----------------+-------+
| id | commodity_code | count |
+----+----------------+-------+
|  1 | C00321         |   100 |
+----+----------------+-------+
1 row in set (0.00 sec)

使用Business验证效果

正常情况

还是在IDE中执行DubboBusinessTester类的主函数,程序跑完会自动退出

在程序一切正常的情况下,每个微服务的事物都应该是提交了的,数据保持一致

我们来看一下MySQL中数据的变化

mysql> SELECT * FROM account_tbl; SELECT * FROM order_tbl; SELECT * FROM storage_tbl;
+----+---------+-------+
| id | user_id | money |
+----+---------+-------+
|  1 | U100001 |   599 |
+----+---------+-------+
1 row in set (0.00 sec)

+----+---------+----------------+-------+-------+
| id | user_id | commodity_code | count | money |
+----+---------+----------------+-------+-------+
|  1 | U100001 | C00321         |     2 |   400 |
+----+---------+----------------+-------+-------+
1 row in set (0.00 sec)

+----+----------------+-------+
| id | commodity_code | count |
+----+----------------+-------+
|  1 | C00321         |    98 |
+----+----------------+-------+
1 row in set (0.00 sec)

从3个表的数据可以看到:账户余额扣减了400块;订单表增加了1条记录;商品库存扣减了2个

这个结果是程序的逻辑是一致的,说明事务没有问题

异常情况

其实即使不加入分布式事务的控制,一切都正常情况下,事务本身就不会有问题的

所以我们来重点关注,当程序出现异常时的情况

现在我把BusinessServiceImpl的抛异常的代码注释放开,然后再执行一次DubboBusinessTester,来看看有什么情况发生

		@Override
    @GlobalTransactional(timeoutMills = 300000, name = "dubbo-demo-tx")
    public void purchase(String userId, String commodityCode, int orderCount) {
        LOGGER.info("purchase begin ... xid: " + RootContext.getXID());
        storageService.deduct(commodityCode, orderCount);
        orderService.create(userId, commodityCode, orderCount);
      
        //放开这句抛异常的注释,模拟程序出现异常
        throw new RuntimeException("portman's foooooobar error.");

    }

接着,我再一次执行DubboBusinessTester,执行过程中在控制台可以看到异常报错信息

Exception in thread "main" java.lang.RuntimeException: portman's foooooobar error.

现在我们再看一下MySQL里的数据变化,发现数据没有任何变化,说明分布式事务的控制已经起作用了

待思考问题

上面的步骤只是演示了seata最简单的demo程序,更多更复杂的情况后续大家可以一起讨论和验证

学习过程中还有一些问题和疑惑,后续进一步学习

  • 全局锁对性能的影响程度
  • undo_log日志可以回滚到原来状态,但是如果数据状态已经发生变化如何处理(比如增加的用户积分已经被别的本地事务花掉了)

参考文献

  • Seata 是什么?
  • 快速开始

作者信息

许晓加,金蝶软件架构师

Github

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

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

相关文章

探讨3D沉浸式在线会议系统的研发 - Meta演示的元宇宙虚拟化身多人对话场景,Web端现在也可以实现了 !

要实现一个元宇宙多人会议系统,关键技术有: 1. 3D虚拟空间的构建(含光影特效、虚拟现实和增强现实) 2. 3D虚拟化身的构建(含动画、表情、语音) 3. 多人角色管理 4. 会话控制和信息同步 5. 语音合成 6…

免费的鼠标连点器电脑版教程!官方正版!专业鼠标连点器用户分享教程!2024最新

电脑技术的不断发展,许多用户在日常工作和娱乐中,需要用到各种辅助工具来提升效率或简化操作,而电脑办公中,鼠标连点器作为一种能够模拟鼠标点击的软件,受到了广大用户的青睐。本文将为大家介绍一款官方正版的免费鼠标…

对接海康sdk-linux下复制jar包中resource目录的文件夹

背景 在集成海康sdk时,需要将一些组件放到项目中作为静态资源,并且海康的sdk初始化也需要加载这些静态资源,在windows下,使用一些File路径的方式是可以正确加载的,但是在linux上就会加载失败。 首先我是将海康的sdk组件放到resource下的,并且按照windows和linux设置了两…

考虑数据库粒度的设计-提升效率

目录 概要 场景 设计思路 小结 概要 公开的资料显示,数据库粒度是:“在数据库领域,特别是数据仓库的设计中,粒度是一个核心概念,它直接影响到数据分析的准确性和存储效率。粒度的设定涉及到数据的详细程度和精度&…

CH11_JS的多重循环

第11章:Javascript的多重循环 本章目标 掌握二重循环的使用 掌握二重循环的控制语句的使用 课程回顾 循环控制有那几种方式 讲解内容 1. 回顾练习 需求说明 某次程序大赛,AI2101班有4名学员参加,学员的成绩由用户输入,计算…

文件系统技术架构分析

一文读懂:什么是文件系统 ,有哪几类? ▉ 什么是文件系统? 技术大拿眉头皱了皱,忍住快要爆发的情绪。解释到: 数据以二进制形式存储于介质,但高低电平含义难解。文件系统揭秘这些二进制背后的意…

【踩坑】修复pyinstaller报错 No module named pkg_resources.extern

转载请注明出处:小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你,欢迎[点赞、收藏、关注]哦~ 报错如下: 修复方法: pip install --upgrade setuptools pippyinstaller -F -w main.py --hidden-importpkg_resources.py2_wa…

前端位置布局汇总

HTML中脱离文档流的元素有: position: absolute - 元素相对于最近的已定位(非 static)祖先元素定位。 position: fixed - 元素相对于浏览器窗口定位。 float: left 或 float: right - 元素向左或向右浮动,周围的内容会环绕它。 …

认识流式处理框架Apache Flink

目录 一、Apache Flink 的基础概念 1.1 Apache Flink是什么? 1.2 Flink的定义 二、Apache Flink 的发展史 2.1 Flink前身Stratosphere 2.2 Flink发展时间线及重大变更 三、Flink核心特性 3.1 批流一体化 3.2 同时支持高吞吐、低延迟、高性能 3.3 支持事件时…

探索Linux:开源世界的无限可能

Linux是一款开源操作系统,它的起源可以追溯到上世纪90年代初。这个故事始于一个名叫Linus Torvalds的芬兰大学生,他在1983年开始编写一个用于个人电脑的操作系统内核。在他的努力下,Linux逐渐发展成为一个稳定而强大的操作系统。 然而&#…

分数的表示和运算方法fractions.Fraction()

【小白从小学Python、C、Java】 【考研初试复试毕业设计】 【Python基础AI数据分析】 分数的表示和运算方法 fractions.Fraction() 选择题 以下代码三次输出的结果分别是? from fractions import Fraction a Fraction(1, 4) print(【显示】a ,a) b Fraction(1, 2…

网络基础:BGP协议

BGP(边界网关协议,Border Gateway Protocol)是一种用于在不同自治系统(Autonomous Systems,AS)之间交换路由信息的路径向量协议。BGP是互联网的核心路由协议之一,负责管理和维护互联网范围内的路…

为企业知识库选模型?全球AI大模型知识库RAG场景基准测试排名

大语言模型常见基准测试 大家对于AI模型理解和推理能力的的基准测试一定非常熟悉了,比如MMLU(大规模多任务语言理解)、GPQA(研究生级别知识问答)、GSMSK(研究生数学知识考察)、MATH&#xff08…

WordPress作品设计素材图片站资讯文章教程uigreat主题

主题介绍 uigreat主题是一款wordpress作品主题,发布设计作品素材文章,适合作品展示、设计等站点使用等,这款主题都非常合适。 1、自适应设计,PC、平板、手机等均可正常浏览; 2、图片缩略图可自定义高度,主…

摸鱼大数据——Spark SQL——DataFrame详解一

1.DataFrame基本介绍 DataFrame表示的是一个二维的表。二维表,必然存在行、列等表结构描述信息​表结构描述信息(元数据Schema): StructType对象字段: StructField对象,可以描述字段名称、字段数据类型、是否可以为空行: Row对象列: Column对象&#xff…

服务器BMC基础知识总结

前言 因为对硬件方面不太理解,所以打算先从服务器开始学习,也想和大家一起分享一下,有什么不对的地方可以纠正一下哦!谢谢啦!互相学习共同成长~ 1.BMC是什么? 官方解释:BMC全名Baseboard Mana…

【聚星文社 绘唐3】MJ版一键AI工具使用文档

MJ版一键AI工具使用文档 绘唐地址下载 欢迎使用MJ版一键AI工具!这个工具可以帮助您快速生成各种类型的文本,包括文章、对话、代码等等。 使用方法: 登录:首先,您需要登录到您的MJ版账户。如果您还没有账户&#xff0…

Spring AOP源码篇二之 代理工厂ProxyFactory学习

了解AspectJ表达式以及PointCut、Advice、Advisor后,继续学习Spring AOP代理工厂 AspectJ表达式参考:Spring AOP之AspectJ表达式-CSDN博客 PointCut、Advice、Advisor参考:Spring AOP源码篇一之 PointCut、Advice、Advisor学习-CSDN博客 简单…

从零开始实现大语言模型(四):简单自注意力机制

1. 前言 理解大语言模型结构的关键在于理解自注意力机制(self-attention)。自注意力机制可以判断输入文本序列中各个token与序列中所有token之间的相关性,并生成包含这种相关性信息的context向量。 本文介绍一种不包含训练参数的简化版自注意力机制——简单自注意…

STM32-PWR和WDG看门狗

本内容基于江协科技STM32视频学习之后整理而得。 文章目录 1. PWR1.1 PWR简介1.2 电源框图1.3 上电复位和掉电复位1.4 可编程电压监测器1.5 低功耗模式1.6 模式选择1.7 睡眠模式1.8 停止模式1.9 待机模式1.10 库函数 2. WDG看门狗2.1 WDG简介2.2 IWDG框图2.3 IWDG键寄存器2.4 …