概览
本篇文章,根据官网代码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