概覽
本篇文章,根據官網代碼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