什么是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。
从日志也可以看出执行了事物回滚的操作。
