如何選擇分布式事務形態

2022-08-11 06:51:13 字數 2517 閱讀 8488

分布式事務有多種主流形態,包括:

這個相信大家都很清楚,在條件允許的情況下,我們應該盡可能地使用單機事務,因為單機事務裡,無需額外協調其他資料來源,減少了網路互動時間消耗以及協調時所需的儲存io消耗,在修改等量業務資料的情況下,單機事務將會有更高的效能。

但單機資料庫由於 業務邏輯解耦等因素進行了資料庫垂直拆分、或者由於單機資料庫效能壓力等因素進行了資料庫水平拆分之後,資料分布於多個資料庫,這時若需要對多個資料庫的資料進行協調制更,則需要引入分布式事務。

分布式事務的模式有很多種,那究竟要怎麼選擇適合業務的模式呢?以下我們將從使用場景、效能、開發成本這幾個方面進行分析。

基於訊息實現的事務適用於分布式事務的提交或回滾只取決於事務發起方的業務需求,其他資料來源的資料變更跟隨發起方進行的業務場景。

舉個例子,假設存在業務規則:某筆訂單成功後,為使用者加一定的積分。

在這條規則裡,管理訂單資料來源的服務為事務發起方,管理積分資料來源的服務為事務跟隨者。

從這個過程可以看到,基於訊息佇列實現的事務存在以下操作:

我們可以看到它的整體流程是比較簡單的,同時業務開發工作量也不大:

可以看到該事務形態過程簡單,效能消耗小,發起方與跟隨方之間的流量峰谷可以使用佇列填平,同時業務開發工作量也基本與單機事務沒有差別,都不需要編寫反向的業務邏輯過程。因此基於訊息佇列實現的事務是我們除了單機事務外最優先考慮使用的形態。

但是基於訊息實現的事務並不能解決所有的業務場景,例如以下場景:某筆訂單完成時,同時扣掉使用者的現金。

這裡事務發起方是管理訂單庫的服務,但對整個事務是否提交並不能只由訂單服務決定,因為還要確保使用者有足夠的錢,才能完成這筆交易,而這個資訊在管理現金的服務裡。這裡我們可以引入基於補償實現的事務,其流程如下:

以上這個是正常成功的流程,異常流程需要回滾的話,將額外傳送遠端呼叫到現金服務以加上之前扣掉的金額。

以上流程比基於訊息佇列實現的事務的流程要複雜,同時開發的工作量也更多:

可以看到,該事務流程相對於基於訊息實現的分布式事務更為複雜,需要額外開發相關的業務回滾方法,也失去了服務間流量削峰填谷的功能。但其僅僅只比基於訊息的事務複雜多一點,若不能使用基於訊息佇列的最終一致性事務,那麼可以優先考慮使用基於補償的事務形態。

(題外話:阿里gts也是利用補償實現,只不過補償**自動生成,無需業務干預,同時接管應用資料來源,禁止業務修改處於全域性事務狀態中的記錄。)

然而基於補償的事務形態也並非能實現所有的需求,如以下場景:某筆訂單完成時,同時扣掉使用者的現金,但交易未完成,也未被取消時,不能讓客戶看到錢變少了。

這時我們可以引入tcc,其流程如下:

以上是正常完成的流程,若為異常流程,則需要傳送遠端呼叫請求到現金服務,撤銷凍結的金額。

以上流程比基於補償實現的事務的流程要複雜,同時開發的工作量也更多:

tcc實際上是最為複雜的一種情況,其能處理所有的業務場景,但無論出於效能上的考慮,還是開發複雜度上的考慮,都應該盡量避免該類事務。

saga可以看做乙個非同步的、利用佇列實現的補償事務。

其適用於無需馬上返回業務發起方最終狀態的場景,例如:你的請求已提交,請稍後查詢或留意通知 之類。

將上述補償事務的場景用saga改寫,其流程如下:

以上為成功的流程,若現金服務扣除金額失敗,那麼,最後一步訂單服務將會更新訂單狀態為失敗。

其業務編碼工作量比補償事務多一點,包括以下內容:

但其相對於補償事務形態有效能上的優勢,所有的本地子事務執行過程中,都無需等待其呼叫的子事務執行,減少了加鎖的時間,這在事務流程較多較長的業務中效能優勢更為明顯。同時,其利用佇列進行進行通訊,具有削峰填谷的作用。

因此該形式適用於不需要同步返回發起方執行最終結果、可以進行補償、對效能要求較高、不介意額外編碼的業務場景。

但當然saga也可以進行稍微改造,變成與tcc類似、可以進行資源預留的形態。

其適用於參與者較少,單個本地事務執行時間較少,並且參與者自身可用性很高的場景,否則,其很可能導致效能下降嚴重。

通過分析我們可以發現,並不存在一種事務形態能解決所有的問題,我們需要根據特定的業務場景選擇合適的事務形態。甚至於有時需要混合多種事務形態才能更好的完成目標,如 上面提到的 訂單、積分、錢包混合的場景:訂單的成功與否需要依賴於錢包的餘額,但不依賴於積分的多少,因此可以混合基於訊息的事務形態以加積分 及 基於補償的事務形態以確保扣錢成功,從而得到乙個效能更好,編碼量更少的形態。

然而目前很多框架都專注於某單一方面的事務形態,如tcc單獨乙個框架,可靠訊息單獨乙個框架,saga單獨乙個框架,他們各自獨立,容易導致以下問題:

為了解決上面提到的問題,easytransaction這個基於spring的分布式事務框架,實現了上述除2pc以外的所有事務形態,並提供了統一的使用介面,完美地解決了以上的問題。其主要特性如下:

若各位對et興趣,可以到 檢視詳細介紹及示例,本文不再深入介紹

不同業務場景應按需引入不同的事務形態,在條件允許的情況下,個人建議按照如下次序選擇對應的事務形態:

單機事務》基於訊息的事務》基於補償的事務》tcc事務

因saga事務的形態需要配合較為明顯的前端業務互動變更,個人建議在單一事務執行過程較長、存在較多子事務,並且無法使用基於訊息的事務形態時使用。

分布式 分布式事務

是資料庫執行過程中的乙個邏輯單位,由乙個有限的資料庫操作序列構成。事務的acid四大特性 原子性 atomicity 事務作為乙個整體被執行。一致性 consistency 從乙個一致的狀態轉換到另乙個一致的狀態。隔離性 isolation 多個事務併發執行時,併發事務之間互相影響的程度。永續性 d...

分布式服務如何設計分布式事務

1 如果a b c強相關 考慮採用tcc框架 try confirm cancel bytetcc,himly 阿里的fescar,seata 推薦使用seata tcc框架 2 如果a 與bc並不強相關 考慮可靠訊息最終一致性解決方案,例如a成功後通過傳送kafka事件,bc監聽事件來處理。roc...

分布式事務 分布式事務的實現

如果在多個服務中需要對不同的資料庫進行操作。因為不同服務操作的資料庫都不同,所以保證在同乙個事務中完成操作顯然是不科學的。那實現分布式事務的思想 1 方法入口,建立一條日誌記錄,狀態定義為初始狀態,即儲存本條日誌記錄 可以儲存在資料庫中,也可以寫出到本地磁碟檔案 2 可以在非同步執行緒或在定時任務中...