一、环境准备
分布式事务组件seata的搭建教程,AT模式,集成nacos、springboot、springcloud、mybatis-plus,数据库采用mysql
1.版本信息
- seata 1.4.0
- nacos 1.4.0
- spring-cloud-alibaba-seata 2.2.0.RELEASE
- spring-cloud-starter-alibaba-nacos-discovery 0.2.1.RELEASE
- springboot 2.0.6.RELEASE
- springcloud Finchley.RELEASE
下载地址
seata-server 1.4.0 : https://github.com/seata/seata/releases/tag/v1.4.0
nacos-server 1.4.0 : https://github.com/alibaba/nacos/releases/tag/1.4.0
2.启动nacos-server
nacos-server下载完毕解压后,目录如下,直接进入bin目录sh startup.sh -m standalone启动,默认端口8848,默认用户名nacos,密码nacos,这里nacos作为一个配置中心及服务注册中心,无需过多配置,直接启动即可
更多详情请参照nacos官方文档
启动后访问http://localhost:8848/nacos,可以成功打开管理页面
3.启动seata-server
seata-server下载完毕解压后,目录如下,其中红框的文件1.4.0版本中默认没有提供,需要自己初始化,nacos-config.sh下载地址:nacos-config.sh,config.txt下载地址:config.txt,logs文件夹自行初始化一个空的即可。(ps:注意目录结构,否则后面脚本执行会报错)
更多详情请参照seata官方文档
4.修改配置
-
config.txt配置改动如下:
-
registry.conf配置改动如下:
这里seata的配置文件提供了多种读取方式,这里我们是nacos,所以type改为nacos,并填写nacos相关配置,其他的注不注释都行。
- file.conf文件改动如下:
mode改为db模式,数据库连接信息修改即可。
- 初始化数据库
-- 创建 seata库、初始化三张系统表
create database seata;
use seata;
DROP TABLE IF EXISTS `branch_table`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
SET character_set_client = utf8mb4 ;
CREATE TABLE `branch_table` (
`branch_id` bigint(20) NOT NULL,
`xid` varchar(128) NOT NULL,
`transaction_id` bigint(20) DEFAULT NULL,
`resource_group_id` varchar(32) DEFAULT NULL,
`resource_id` varchar(256) DEFAULT NULL,
`branch_type` varchar(8) DEFAULT NULL,
`status` tinyint(4) DEFAULT NULL,
`client_id` varchar(64) DEFAULT NULL,
`application_data` varchar(2000) DEFAULT NULL,
`gmt_create` datetime(6) DEFAULT NULL,
`gmt_modified` datetime(6) DEFAULT NULL,
PRIMARY KEY (`branch_id`),
KEY `idx_xid` (`xid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `global_table`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
SET character_set_client = utf8mb4 ;
CREATE TABLE `global_table` (
`xid` varchar(128) NOT NULL,
`transaction_id` bigint(20) DEFAULT NULL,
`status` tinyint(4) NOT NULL,
`application_id` varchar(32) DEFAULT NULL,
`transaction_service_group` varchar(32) DEFAULT NULL,
`transaction_name` varchar(128) DEFAULT NULL,
`timeout` int(11) DEFAULT NULL,
`begin_time` bigint(20) DEFAULT NULL,
`application_data` varchar(2000) DEFAULT NULL,
`gmt_create` datetime DEFAULT NULL,
`gmt_modified` datetime DEFAULT NULL,
PRIMARY KEY (`xid`),
KEY `idx_gmt_modified_status` (`gmt_modified`,`status`),
KEY `idx_transaction_id` (`transaction_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `lock_table`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
SET character_set_client = utf8mb4 ;
CREATE TABLE `lock_table` (
`row_key` varchar(128) NOT NULL,
`xid` varchar(96) DEFAULT NULL,
`transaction_id` bigint(20) DEFAULT NULL,
`branch_id` bigint(20) NOT NULL,
`resource_id` varchar(256) DEFAULT NULL,
`table_name` varchar(32) DEFAULT NULL,
`pk` varchar(36) DEFAULT NULL,
`gmt_create` datetime DEFAULT NULL,
`gmt_modified` datetime DEFAULT NULL,
PRIMARY KEY (`row_key`),
KEY `idx_branch_id` (`branch_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- 创建 order库、业务表、undo_log表
create database seata_order;
use seata_order;
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;
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;
-- 创建 storage库、业务表、undo_log表
create database seata_storage;
use seata_storage;
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;
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;
-- 初始化库存模拟数据
INSERT INTO seata_storage.storage_tbl (id, commodity_code, count) VALUES (1, 'product-1', 9999999);
INSERT INTO seata_storage.storage_tbl (id, commodity_code, count) VALUES (2, 'product-2', 0);
- 启动seata-server
# 初始化seata 的nacos配置
cd conf
sh nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -u nacos -w nacos
# 启动seata-server
cd bin
sh seata-server.sh -p 8091 -m file
命令解析:-h -p 指定nacos的端口地址;-g 指定配置的分组,注意,是配置的分组; -u -w指定nacos的用户名和密码,同样,这里开启了nacos注册和配置认证的才需要指定。
nacos-config.sh就是将config.txt中的所有配置写到nacos中,这里有个别fail的问题不大,只要不是关键环节fail即可,执行完毕入下图:
seata-server启动成功如下图:
二、启动springboot工程
springboot工程demo : https://gitee.com/guozhongkui/seata-nacos
application.properties配置如下(seata配置和前面保持一致,每个工程对应一个服务组,数据库更新即可):
spring.application.name=order-service
server.port=9091
# Nacos 注册中心地址
spring.cloud.nacos.discovery.server-addr = localhost:8848
# seata 服务分组,要与服务端nacos-config.txt中service.vgroup_mapping的后缀对应
#spring.cloud.alibaba.seata.tx-service-group=order-service-group
#seata.registry.type=nacos
#seata.registry.nacos.group=seata-server
#seata.registry.nacos.server-addr=127.0.0.1:8848
#seata.registry.nacos.namespace=""
#seata.registry.nacos.username=nacos
#seata.registry.nacos.password=nacos
seata.config.type=nacos
seata.config.nacos.group=SEATA_GROUP
seata.config.nacos.server-addr=127.0.0.1:8848
seata.config.nacos.namespace=
seata.config.nacos.username=nacos
seata.config.nacos.password=nacos
seata.tx-service-group=order-service-group
seata.service.vgroup-mapping.order-service-group=default
#seata.service.disable-global-transaction=false
logging.level.io.seata = debug
# 数据源配置
spring.datasource.druid.url=jdbc:mysql://localhost:3306/seata_order?allowMultiQueries=true
spring.datasource.druid.driverClassName=com.mysql.jdbc.Driver
spring.datasource.druid.username=root
spring.datasource.druid.password=root
同时启动order-service及storage-service
三、测试
分布式事务成功,模拟正常下单、扣库存
localhost:9091/order/placeOrder/commit
分布式事务失败,模拟下单成功、扣库存失败,最终同时回滚
localhost:9091/order/placeOrder/rollback