上篇文章简单介绍了SpringCloud系列链路追踪神器:Sleuth与Zipkin的搭建及基本用法,今天继续讲解下SpringCloud的分布式事务处理组件:Seata的使用!在分享之前继续回顾下本次SpringCloud的专题要讲的内容:
这次我们将聚焦于当下热门的分布式事务框架Seata,探讨如何在微服务架构中解决跨服务事务一致性的难题。在单体应用中,我们只需使用本地事务即可保证数据一致性,但随着业务拆分到不同微服务中,传统事务机制已无法满足需求。
本教程适合具备以下基础的开发者:
本系列前源码放在附件资源内,可以下载源码一起练习
Seata(Simple Extensible Autonomous Transaction Architecture)是阿里巴巴开源的分布式事务解决方案,提供高性能且易用的分布式事务服务。它支持四种事务模式:
更多原理细节可参考官方文档
registry.conf
文件,配置Nacos作为注册中心:registry {
type = "nacos"
nacos {
serverAddr = "127.0.0.1:8848"
namespace = "public"
cluster = "default"
username = "nacos"
password = "nacos"
}
}
registry.conf
中配置Nacos作为配置中心:config {
type = "nacos"
nacos {
serverAddr = "127.0.0.1:8848"
namespace = "public"
group = "SEATA_GROUP"
username = "nacos"
password = "nacos"
}
}
sh script/config-center/nacos/nacos-config.sh -h 127.0.0.1 -p 8848 -g SEATA_GROUP -u nacos -w nacos
成功上传后,可在Nacos控制台(127.0.0.1:8848/nacos)查看配置。
特别注意service.vgroupMapping
配置项,服务端和客户端必须保持一致。例如:
service.vgroupMapping.my_test_tx_group=default
对应客户端配置:
seata:
tx-service-group: my_test_tx_group
启动Seata Server:
./seata-server.bat -h 127.0.0.1
sh seata-server.sh -h 127.0.0.1
成功启动后,可在Nacos服务列表看到Seata服务注册。
执行Seata提供的建表SQL,创建seata
数据库及相关表。
复制原有工程并重命名:
spring-cloud-nacos-consumer
→ order-server
spring-cloud-nacos-provider
→ stock-server
修改pom.xml中的基础配置:
<artifactId>order-serverartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>order-servername>
在两个模块中添加Seata依赖:
<dependency>
<groupId>io.seatagroupId>
<artifactId>seata-spring-boot-starterartifactId>
<version>1.4.2version>
dependency>
在application.yml中添加Seata配置:
seata:
tx-service-group: my_test_tx_group
创建订单和库存数据库及表结构:
-- 订单库
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`)
);
-- 库存库
CREATE TABLE `stock_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`)
);
订单服务关键代码:
@GlobalTransactional
public void placeOrder(String userId, String commodityCode, Integer count) {
// 创建订单
Order order = new Order()
.setUserId(userId)
.setCommodityCode(commodityCode)
.setCount(count);
orderMapper.insert(order);
// 调用库存服务扣减
stockFeignClient.deduct(commodityCode, count);
}
库存服务关键代码:
public void deduct(String commodityCode, int count) {
if ("product-2".equals(commodityCode)) {
throw new RuntimeException("模拟业务异常");
}
Stock stock = stockMapper.selectByCommodityCode(commodityCode);
stock.setCount(stock.getCount() - count);
stockMapper.updateById(stock);
}
在Gateway中添加路由规则:
spring:
cloud:
gateway:
routes:
- id: order-server
uri: lb://order-server
predicates:
- Path=/order/**
- id: stock-server
uri: lb://stock-server
predicates:
- Path=/stock/**
/order/placeOrder/commit
/order/placeOrder/rollback
通过本教程,我们完成了:
Seata作为一款成熟的分布式事务框架,为微服务架构提供了可靠的事务保障。开发者可以根据业务特点选择合适的事务模式,更多高级配置可参考官方文档。