分布式事務框架Seata客戶端的使用
Seata (Simple Extensible Autonomous Transaction Architecture) 是一種開源的分布式事務解決方案,致力于在微服務架構下提供高效且對業務無侵入的分布式事務服務。Seata 能夠幫助開發者輕松地解決在微服務架構下服務間的數據一致性問題。
圖片
在分布式系統中,一個業務操作通常會涉及到多個服務的協作,這些服務可能會對不同的數據庫進行操作。傳統的分布式事務解決方案(如2PC,即兩階段提交)雖然能夠保證強一致性,但卻在性能和可用性方面存在不小的挑戰。因此,Seata 提出了一種基于AT、TCC、SAGA、XA等模式的輕量級分布式事務協調方案。
Seata 確實支持多種分布式事務模式,包括 AT(自動補償事務)、TCC(Try-Confirm-Cancel)、SAGA 和 XA(擴展的兩階段提交協議)。每種模式都有自己的使用場景和特點:
1. AT模式(Auto-Compensating Transaction)
圖片
- 適用場景:簡單的CRUD操作,不需要特殊處理的業務邏輯。
- 特點:
易于使用,開發者不需要編寫額外的補償邏輯,Seata 會自動為每個分支事務生成撤銷(回滾)邏輯。
性能較好,因為它減少了準備階段的通信開銷。
通過行鎖和UNDO_LOG(回濾日志),加鎖和數據改動被記錄下來,保證在出現錯誤時可以回滾事務。
@Service
public class OrderService {
@GlobalTransactional(timeoutMills = 300000, name = "create-order")
public void createOrder(Order order, Payment payment, Inventory inventory) {
// 更新庫存
inventoryService.reduceStock(inventory);
// 創建支付記錄
paymentService.pay(payment);
// 創建訂單
orderRepository.save(order);
}
}
按照官方配置AT模式后,在方法前面添加GlobalTransactional注解。
AT模式的主要思想就是通過一個中間層進行協調事務的確認和回滾操作,將相應的操作記錄在例如數據庫表里面,在提交后進行事務的信息的刪除,再通過一個全局鎖來避免資源的競爭。其方式對業務代碼不需要侵入。
2. TCC模式(Try-Confirm-Cancel)
圖片
- 適用場景:業務邏輯較為復雜,或者需要明確的業務補償操作。
- 特點:
分為三個操作:Try(嘗試執行業務)、Confirm(確認執行業務)、Cancel(取消執行業務),業務邏輯被拆分成這三部分。
開發者需要自行實現這三個操作,提供更強的業務手動控制能力。
具體的業務操作和補償邏輯是可見的,有助于處理復雜的業務場景。
//定義接口實現注解
@LocalTCC
public interface PaymentService {
// "try" 方法,準備資源,比如凍結用戶資金
@TwoPhaseBusinessAction(name = "preparePay", commitMethod = "commitPay", rollbackMethod = "cancelPay")
boolean preparePay(BusinessActionContext context, String accountId, double amount);
// "confirm" 方法,確認并實際扣除凍結的資金
boolean commitPay(BusinessActionContext context);
// "cancel" 方法,取消操作,解凍之前凍結的資金
boolean cancelPay(BusinessActionContext context);
}
//然后,為接口提供一個實現類,并實現try、confirm和cancel方法:
@Service
public class PaymentServiceImpl implements PaymentService {
@Autowired
private AccountRepository accountRepository;
@Override
public boolean preparePay(BusinessActionContext context, String accountId, double amount) {
// 實現資金的凍結邏輯
// ...
return true;
}
@Override
public boolean commitPay(BusinessActionContext context) {
// 實現實際扣除資金的邏輯
// ...
return true;
}
@Override
public boolean cancelPay(BusinessActionContext context) {
// 實現取消扣款,即解凍資金的邏輯
// ...
return true;
}
}
//最后,在需要執行TCC事務的業務邏輯中注入PaymentService并調用上述方法:
@Service
public class OrderService {
@Autowired
private PaymentService paymentService;
@GlobalTransactional
public void createOrder(Order order, String accountId, double amount) {
// TCC try 階段
boolean result = paymentService.preparePay(null, accountId, amount);
if (!result) {
throw new RuntimeException("Payment preparation failed.");
}
// TCC confirm 或 cancel 階段將由Seata框架根據全局事務的最終狀態自動調用
// ...
}
}
其本質的思想就是通過代碼編寫確認機制和補償機制,這種方式需要對業務的代碼的侵入。
3. SAGA模式
- 適用場景:長事務場景,例如一系列的步驟或服務調用需要在整體上保持一致性。
- 特點:
基于狀態機實現,每個步驟都對應狀態遷移過程中的一個節點。
不適用于標準的兩階段提交,而是將一個全局事務分解成多個局部事務,通過定義前向操作和反向補償操作來保證整體一致性。
適用于事務執行時間較長的業務流程,減少了鎖資源的持有時間。
// 偽代碼,僅為示例說明
StateMachineBuilder stateMachineBuilder = StateMachineBuilderFactory.create();
StateMachine stateMachine = stateMachineBuilder
.state("Start")
.initial("CreateOrder")
.to("ReserveInventory").on("InventoryReserved")
.to("CancelOrder").on("InventoryReserveFailed")
.step("ReserveInventory")
.to("ProcessPayment").on("PaymentProcessed")
.to("RevertInventory").on("PaymentProcessFailed")
.step("ProcessPayment")
.to("End").on("Success")
.step("CancelOrder")
.compensateWith("CancelOrderOperation")
.step("RevertInventory")
.compensateWith("RevertInventoryOperation")
.build();
stateMachine.start();
使用狀態機來進行多事務的描述其本質的思想就是對多事務進行確認和補償,這種也會需要對業務代碼的侵入。
4. XA模式
圖片
- 適用場景:需要嚴格的ACID事務,并且各參與方(數據庫、消息中間件等)支持XA接口。
- 特點:
基于兩階段提交(2PC),第一階段是準備階段,第二階段是提交或回濾階段。
實現了跨資源管理器的全局事務。
通常比AT模式效率低,因為它在第一階段結束時需要所有參與者就事務結果達成一致,然后在第二階段進行提交或回滾。
將動態的代理數據源替換成XA模式,然后和AT模式一樣,在需要的方法前面添加GlobalTransactional注解
@Service
public class OrderService {
@Autowired
private OrderRepository orderRepository;
@GlobalTransactional
public void createOrder(Order order) {
// 此處的數據庫操作會自動被Seata管理
orderRepository.save(order);
// ...其他可能涉及數據庫操作的代碼
}
}
其本質的思想就是與AT模式類似,但是需要基于數據庫能支持XA模式才能運行,AT模式是在中間層進行確認和回滾的日志記錄,而XA模式是將記錄交給數據庫來運行,也避免了AT模式下手動操作數據導致問題。XA模式不需要侵入業務代碼。
圖片
在選用分布式事務模式時,需要根據具體業務場景和對一致性的需求做出選擇。每種模式都有其優勢和局限,沒有絕對的“最佳”選擇。對于開發者來說,了解各模式的內部機制和可能的性能影響是非常重要的。