分布式事務(wù)TCC框架
- https://github.com/yu199195/happylifeplat-tcc
- 支持spring cloud, dubbo
tcc 定義
- 服務(wù)層分布式事務(wù) TCC青自,基于服務(wù)層面的
- 在TCC中這些接口為:try蚀同、confirm堪滨、cancel(縮寫為TCC)桑驱。TCC事務(wù)管理器會使用try将塑、confirm北启、cancel接口協(xié)調(diào)多個服務(wù)進(jìn)行事務(wù)處理
image.png
Try: 嘗試執(zhí)行業(yè)務(wù)
? 完成所有業(yè)務(wù)檢查(一致性)
? 預(yù)留必須業(yè)務(wù)資源(準(zhǔn)隔離性)
Confirm:確認(rèn)執(zhí)行業(yè)務(wù)
? 真正執(zhí)行業(yè)務(wù)
? 不作任何業(yè)務(wù)檢查
? 只使用Try階段預(yù)留的業(yè)務(wù)資源
? Confirm操作要滿足冪等性
Cancel: 取消執(zhí)行業(yè)務(wù)
? 釋放Try階段預(yù)留的業(yè)務(wù)資源
? Cancel操作要滿足冪等性
- 流程圖
image.png
- 分析
/**
* 訂單支付接口(注意這里模擬的是創(chuàng)建訂單并進(jìn)行支付扣減庫存等操作)
* @param count 購買數(shù)量
* @param amount 支付金額
* @return
*/
@Override
public String orderPay(Integer count, BigDecimal amount) {
final Order order = buildOrder(count, amount);
final int rows = orderMapper.save(order);
if (rows > 0) {
paymentServiceImpl.makePayment(order);
}
return "success";
}
@Tcc(confirmMethod = "confirmOrderStatus", cancelMethod = "cancelOrderStatus")
public void makePayment(Order order) {
order.setStatus(OrderStatusEnum.PAYING.getCode());
orderMapper.update(order);
//扣除用戶余額
AccountDTO accountDTO = new AccountDTO();
accountDTO.setAmount(order.getTotalAmount());
accountDTO.setUserId(order.getUserId());
LOGGER.debug("===========執(zhí)行springcloud扣減資金接口==========");
accountClient.payment(accountDTO);
//進(jìn)入扣減庫存操作
InventoryDTO inventoryDTO = new InventoryDTO();
inventoryDTO.setCount(order.getCount());
inventoryDTO.setProductId(order.getProductId());
inventoryClient.decrease(inventoryDTO);
}
- 1: 創(chuàng)建訂單并進(jìn)行支付扣減庫存等操作
- 2:創(chuàng)建訂單
- 3:更改訂單狀態(tài)卜朗,扣減用戶余額 [賬戶服務(wù)]
- 4:扣減庫存操作 [庫存服務(wù)]
看當(dāng)前訂單系統(tǒng),的tcc的確認(rèn)和取消方法
/**
* 確認(rèn)提交成功 訂單為支付成功的狀態(tài)
* @param order
*/
public void confirmOrderStatus(Order order) {
order.setStatus(OrderStatusEnum.PAY_SUCCESS.getCode());
orderMapper.update(order);
LOGGER.info("=========進(jìn)行訂單confirm操作完成================");
}
/**
* 提交失敗咕村,更新訂單為 支付失敗的狀態(tài)
* @param order
*/
public void cancelOrderStatus(Order order) {
order.setStatus(OrderStatusEnum.PAY_FAIL.getCode());
orderMapper.update(order);
LOGGER.info("=========進(jìn)行訂單cancel操作完成================");
}
源碼分析
- aop攔截注解
- 每次try會生成在每個微服務(wù)的數(shù)據(jù)庫中事務(wù)記錄表中添加一條記錄
- 后臺開啟30秒線程定時(shí)對 事務(wù)記錄做補(bǔ)償 執(zhí)行cancel或者confirm方法
- 沒有一個獨(dú)立的協(xié)調(diào)服務(wù)聊替,都是在本地完成的