前言
-
什麼是分佈式事務
在業務系統中,如果發起了一個rpc請求(遠程調用請求)訪問了其他的服務。
那麼該服務的事務我們調用方是無法控制的,比如回滾或者提交。
所以這就涉及到數據到一致性問題。
就如同下面這種情況
此次業務調用中,發起者是Business,如果調用到rpc服務中,三有一是出現異常到情況,那麼就需要統一回滾,就算之前有某個調用成功到服務,也需要回滾。
事務要麼一起成功,要麼一起失敗,所以數據纔可以一致。 -
seate怎麼實現分佈式事務
seate實現分佈式事務的方法如下圖
其實就是維護”一個大的事務“,子事務成功,纔可以全部提交。
開始
模擬場景
項目地址
參考裏面的springboot
1. 安裝一個mysql(我使用的是5.7)
2.初始化一個數據庫用這sql文件 [sql/init_db.sql](https://github.com/seata/seata-samples/blob/master/springboot/src/main/resources/sql/initial_db.sql)
3. 修改yml的配置,設置mysql的用戶名和密碼(https://github.com/seata/seata-samples/blob/master/springboot/src/main/resources/application.yml#L13-L35)
4. 設置dubbo的註冊中心 `zookeeper://localhost:2181`
5.啓動 seata server
6. 啓動 SeataSpringbootApp .
7. 訪問 http://127.0.0.1:9999/demo//asset/assign , 觀察事務的一致性
說明:
1.zookeeper我使用的是zookeeper:3.5.5
2.seata server地址,啓動seata/server/src/main/java/io/seata/server/Server.java
代碼
SeataSpringbootApp主要邏輯
這是我們訪問的接口
@RequestMapping(value = "/asset/assign")
@ResponseBody
public String assetAssign() {
LOGGER.info("welcome to deposit");
String result;
try {
AssetAssign assetAssign = assignService.increaseAmount(
ASSET_ID);
result = assetAssign.toString();
} catch (Exception e) {
result = ExceptionUtils.getMessage(e);
}
return result;
}
主要的業務方法是這個increaseAmount
@Override
@Transactional
@GlobalTransactional
public AssetAssign increaseAmount(String id) {
LOGGER.info("Assign Service Begin ... xid: " + RootContext.getXID() + "\n");
//增加資產
AssetAssign assetAssign = assignRepository.findById(id).get();
assetAssign.setStatus("2");
assignRepository.save(assetAssign);
// 調用rpc服務增加資產
assetService.increase();
return assetAssign;
}
這裏主要是assetService.increase,這個rpc。
@Override
public int increase() {
LOGGER.info("Asset Service Begin ... xid: " + RootContext.getXID() + "\n");
Asset asset = assetRepository.findById(ASSET_ID).get();
asset.setAmount(asset.getAmount().add(new BigDecimal("1")));
assetRepository.save(asset);
//如果上面調用方沒有GlobalTransactional註解的話,那麼就會出現下面的情況
//這裏是遠程的方法,拋出異常,數據已經插入到數據庫裏面了
throw new RuntimeException("test exception for seata, your transaction should be rollbacked,asset=" + asset);
}
加了GlobalTransactional註解,那麼調用到遠程rpc,後面遠程拋出RuntimeException,那麼事務會回滾,實現了我們的目的。