分布式事务Seata实战
Github地址: https://github.com/seata/seata
官方Demo地址: https://github.com/seata/seata-samples
官网地址: https://seata.io/zh-cn
理论知识参考官网及CSDN
技术选型
- 注册中心: nacos
1.2.0
- 服务间调用:openfeign
2.0.0
- 持久层:mybatis-plus
3.1.1
- 数据库:mysql 5.7.20
- SpringBoot:2.0.6.RELEASE
- SpringCloud:Finchley.RELEASE
- JDK:1.8
- Seata:1.1.0
Demo源码下载
官方Demo: https://github.com/seata/seata-samples/tree/master/springcloud-nacos-seata
1.Nacos-server
参考官方https://nacos.io/zh-cn/docs/quick-start.html
2.Seata-Server
下载最新1.1.0版本,注意官方版本中只有file方式的配置文件
nacos配置文件及脚本需在源码中获取,点此
2.1修改conf/registry配置
设置type,serverAddr
注意这里有一个坑,serverAddr不能带‘http://’前缀
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "nacos"
nacos {
serverAddr = "localhost:8848"
namespace = ""
cluster = "default"
}
}
config {
# file、nacos 、apollo、zk、consul、etcd3
type = "nacos"
nacos {
serverAddr = "localhost:8848"
namespace = ""
group = "SEATA_GROUP"
}
}
2.2 修改conf/nacos-config.txt
注意Seata1.0及以上使用vgroupMapping,其他版本使用vgroup_mapping
service.vgroupMapping.order-service-group=default
service.vgroupMapping.storage-service-group=default
service.vgroupMapping.${your-service-gruop}=default
${your-service-gruop}为自己定义的服务组名称,服务中的application.properties文件里配置服务组名称。
2.3 启动seata-server
-
推送配置
nacos-config.sh 127.0.0.1 #脚本中已拼接端口8848
参数参考:
-h: host, the default value is localhost. -p: port, the default value is 8848. -g: Configure grouping, the default value is 'SEATA_GROUP'. -t: Tenant information, corresponding to the namespace ID field of Nacos, the default value is ''.
-
启动
bin/seata-server.bat
3.其他说明
3.1数据库
-- 创建 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);
3.2应用配置
registry.conf
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "nacos"
nacos {
serverAddr = "127.0.0.1:8848"
namespace = ""
cluster = "default"
}
}
config {
# file、nacos 、apollo、zk、consul、etcd3、springCloudConfig
type = "nacos"
nacos {
serverAddr = "127.0.0.1:8848"
namespace = ""
group = "SEATA_GROUP"
}
}
application.yml(重点配置)
spring:
cloud:
alibaba:
seata:
tx-service-group: storage-service-group #与配置文件中一致
3.3测试
-
分布式事务成功,模拟正常下单、扣库存
localhost:9091/order/placeOrder/commit
-
分布式事务失败,模拟下单成功、扣库存失败,最终同时回滚
localhost:9091/order/placeOrder/rollback