概览
本篇文章,根据官网代码demo演示而来
springboot、dubbo、seata实现分布式事务整合 DEMO
操作步骤如下:
- 1.seata-server端,修改server配置
- 2.client端(你自己的项目),引入配置文件,修改配置文件
- 3.数据源代理设置
- 4.创建数据库表
- 5.启动注册中心(ZK),启动server,启动client(包括订单服务,库存服务)
1.此demo技术选型及版本信息
运行环境 | 版本要求 |
---|---|
jdk | 1.8+ |
Spring Boot | 1.5+ |
MySQL | 5.7+ |
ZooKeeper | 3.4+ |
Seata | 1.0.0 |
Dubbo | 2.6.5 |
2.demo概况
- springboot-base:存储公共调用的基类接口,mapper接口,Model层的类等,可mvn install后,供另外三个module调用。
- springboot-dubbo-storage:库存服务;
- springboot-dubbo-order:订单服务;
- springboot-dubbo-client:RPC消费者,提供对外接口;
order服务关键代码如下:
@Override
@GlobalTransactional(rollbackFor = Exception.class)
public void createOrder(OrderDTO orderDTO) {
//1、远程方法 扣减库存
storageService.decreaseStorage(storageDTO);
//2、本地方法 创建订单
orderMapper.createOrder(order);
}
3.创建业务数据库
- seata_order:存储订单的数据库;
- seata_storage:存储库存的数据库;
4.seata 组件
1,配置Seata数据源
/**
* seata数据源
*
* init datasource proxy
* @Param: druidDataSource datasource bean instance
* @Return: DataSourceProxy datasource proxy
*/
@Bean
public DataSourceProxy dataSourceProxy(DruidDataSource druidDataSource){
return new DataSourceProxy(druidDataSource);
}
2,Seata初始化
/**
* 配置全局事务扫描器。有两个参数,一个是应用名称,一个是事务分组
*
* @return
*/
@Bean
public GlobalTransactionScanner globalTransactionScanner() {
return new GlobalTransactionScanner("springboot-dubbo-storage", "my_test_tx_group");
}
3,配置注册中心,内容在file.conf和registry.conf。
4,注解标记事务方法,在订单创建的方法上,加上@GlobalTransactional注解即可。
5.启动测试(注意先后顺序)
依次启动Seata、springboot-dubbo-storage、springboot-dubbo-order、springboot-dubbo-client后,打开postman测试,配置测试参数为:
正常情况:
请求地址:http://localhost:18090/order/create
请求方式:post
请求内容(body):
{
"userId":1,
"productId":1,
"count":10,
"money":100
}
通过我们访问
/order
下单接口,根据响应的内容我们确定商品已经购买成功数据库内的
商品库存
有所扣减
6.测试异常情况
我们模拟userId为666时,会出现异常
请求地址:http://localhost:18090/order/create
请求方式:post
请求内容(body):
{
"userId":666,
"productId":8,
"count":5,
"money":50
}
@Override
@GlobalTransactional(rollbackFor = Exception.class)
public void createOrder(OrderDTO orderDTO) {
log.info("开始全局事务。XID=" + RootContext.getXID());
// 库存
StorageDTO storageDTO = new StorageDTO();
storageDTO.setTotal(orderDTO.getCount());
storageDTO.setProductId(orderDTO.getProductId());
//1、远程方法 扣减库存
storageService.decreaseStorage(storageDTO);
//2、本地方法 创建订单
orderDTO.setId(order_id.incrementAndGet());
Order order = new Order();
BeanUtils.copyProperties(orderDTO,order);
orderMapper.createOrder(order);
// 构造异常抛出 在addOrder报错后,会有全局事务的rollback过程
if (orderDTO.getUserId() == 666) {
throw new RuntimeException("分布式事务异常..." + orderDTO.getId());
}
}
此时我们可以发现下单后数据库数据并没有任何改变 ,扣减的库存和创建的订单都回滚了
参考链接
- https://seata.io/zh-cn/
- https://seata.io/zh-cn/docs/user/quickstart.html
- https://seata.io/zh-cn/blog/springboot-dubbo-mybatisplus-seata.html