分布式事物seata的AT模式实战

什么是seata?

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

seata官网:https://seata.apache.org/zh-cn/docs/overview/what-is-seata

seata中三大核心角色?

  • 事务协调者(TC),它的作用是维护全局和分支事务的状态,驱动全局事务提交或者回滚,是事务协调者组件的具体实现,TC由SEATA官方提供。
  • 事务管理器(TM),事务管理器用于定义全局事务的范围,开始全局事务提交或者回滚全局事务都是由TM来决定了。
  • 资源管理器(RM),用于管理分支事务处理的资源,并且报告分支事务的状态,并驱动分支事务提交或者回滚。

seata的AT模式是什么?

AT模式是seata中最为常用的分布式事物处理模式,AT模式分两个阶段执行。它的基本原理如下:

阶段1:准备阶段

上图代表要分别执行两个数据库操作,左侧是往customer表插入一条ID=1的记录。右侧是往order表插入一条ID=1023的记录。

事物管理者(TM)下达指令给到事物协调者(TC),事物协调者(TC)再开启两个分支事物,控制RM1、RM2的事物执行。

这个阶段数据已经插入到数据库表中,同步会生成反向SQL,反向就是删除数据库表记录的SQL。如果其中某个环节出现了问题,通过执行反向SQL的方式,达到数据回滚,保持数据一致性。

阶段2:提交阶段(正常执行)

事物管理者(TM)下达全局提交的指令给到事物协调者(TC),RM1、RM2都执行完毕,且没有出现任何问题,此时会将上一步产生的反向SQL删掉,整个过程结束。

阶段2:回滚阶段(执行出错)

当阶段一中任何一个资源管理器(RM)执行出错,事物管理者(TM)下达全局回滚的指令给到事物协调者(TC),RM1、RM2执行阶段一产生的反向SQL,将之前插入的记录根据ID从数据库中删除,保证数据一致性。

AT模式开发实战

下面用代码演示AT模式的执行过程,包括环境搭建,程序运行。

环境搭建

在docker上部署MySQL、Nacos。

MySQL部署

在docker中执行下面的命令,创建MySQL容器:

docker run -d --name mysql8 --hostname mysql8 \

--restart=always \

-p 3306:3306 \

-e MYSQL_ROOT_PASSWORD=MySQL数据库密码 \

-e TZ=Asia/Shanghai \

-v mysql-data:/var/lib/mysql \

mysql:8.0.22 \

--character-set-server=utf8mb4 \

--collation-server=utf8mb4_unicode_ci \

--default-time-zone=+8:00

需要把密码改下,然后执行。就会在docker中启动MySQL的容器。

Nacos部署

在MySQL数据中创建名称为nacos_config的数据, 执行数据库创建的脚本mysql-schema.sql,脚本下载地址:

https://github.com/alibaba/nacos/blob/develop/distribution/conf/mysql-schema.sql

执行完成后,数据库就初始化好了。

执行下面的命令,创建nacos容器:

docker run -d --name nacos --restart=always \

-p 8080:8080 -p 8848:8848 -p 9848:9848 \

-e MODE=standalone \

-e SPRING_DATASOURCE_PLATFORM=mysql \

-e MYSQL_SERVICE_HOST=MySQL数据库的IP地址 \

-e MYSQL_SERVICE_PORT=3306 \

-e MYSQL_SERVICE_DB_NAME=nacos_config \

-e MYSQL_SERVICE_USER=root\

-e MYSQL_SERVICE_PASSWORD=MySQL数据库密码 \

-e MYSQL_SERVICE_DB_PARAM="characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false&serverTimezone=Asia/Shanghai" \

-e NACOS_AUTH_TOKEN=SecretKey012345678901234567890123456789012345678901234567890123456789 \

-e NACOS_AUTH_IDENTITY_KEY=ikey \

-e NACOS_AUTH_IDENTITY_VALUE=idvalue \

nacos/nacos-server:latest

把命令中的IP和密码改为自己的,然后执行命令,就可以在docker中成功创建nacos容器。

浏览器访问 nacos所在服务器的ip+8080端口,便可以访问nacos管理控制台。

默认的用户名和密码都是nacos

运行示例代码

下面的这个示例项目代码,完成两个事情,模拟订单的创建和库存的减少。

把下面地址的示例代码文件进行下载,然后用idea打开:

https://download.csdn.net/download/liangmengbk/92437218

整个示例项目由三个独立的应用程序组成,tm代表事物管理者,rm1、rm2分别代表两个资源管理者。

tm负责整体事物。

rm1是完成订单的创建。

rm2是完成库存的递减。

打开项目后,需要配置文件中的一些配置项。

把三个应用的配置文件中对应的IP、用户名、密码都改成自己的。

然后把三个应用都启动。

通过下面的方式,在idea快捷访问这个

点击'在http客户端中生成请求',会自动打开这样的一个快捷访问文件

把请求地址改成下面的地址:

GET http://localhost:8000/sale?orderId=114\&memberId=2\&goodsId=1\&quantity=20

点击请求地址前面的三角符号,发送请求

控制台打印了执行的结果信息

完成了订单的创建,完成了库存的减少。

在tm的控制台,可以看到开始全局事物,提交事物的相关日志。

在rm1、rm2的控制台,可以看到分支事物的提交相关日志。

此时再看下数据库表记录,会发现rm-db-1数据库的order表新增了订单。

rm-db-2的库存表,减少了库存。

以上演示的是正常情况,下面演示一下异常情况,减少库存的时候,设置一个不存在的数字。

比如1号商品只有160个库存,在创建订单时,减少1000个库存。

把quantity改成1000后,再调用接口,发现报错500。

从日志也可以看出执行了事物回滚的操作。

相关推荐
shaohaoyongchuang1 小时前
01-分布式基础-创建微服务项目
分布式·微服务·架构
失伟3 小时前
kafka教程(新手使用单机版)
分布式·kafka
Xyz996_3 小时前
Ceph分布式存储
分布式·ceph
绝顶少年4 小时前
Redis 五大核心应用场景实战解析:缓存、会话、排行榜、分布式锁与消息队列
redis·分布式·缓存
武子康4 小时前
Java-181 OSS 实战指南:Bucket/外链/防盗链/计费与常见坑
java·大数据·分布式·oss·云存储·fastdfs·ali
沧海寄馀生4 小时前
Apache Hadoop生态组件部署分享-Impala
大数据·hadoop·分布式·apache
写bug的小屁孩4 小时前
5.Kafka-HW重要特性与场景分析
分布式·中间件·kafka
wangmengxxw4 小时前
微服务-服务容错(续)
微服务·云原生·架构·服务容错
嘉禾望岗5035 小时前
spark计算框架与RDD特性介绍
大数据·分布式·spark