原創宣告:本文系作者原創,謝絕個人、媒體、公眾號或網站未經授權轉載,違者追究其法律責任。
基於 XA 協議的應用場景
XA 協議在架構上與 TCC 模型相比,最大的不同是 XA 直接作用於資源層,而後者作用於服務層。
資源層更普適,並且對業務幾乎沒有侵入,但是為了適應各種業務場景使用,需要嚴格遵循事務 ACID 特性;服務層更接近業務,可以針對不同業務做特定的優化處理,追求更高的極限效能。
當然,並不是說 XA 協議只能作用於單個服務內部的多資源場景,跨服務的多資源場景也是可以的,只不過同樣需要額外的事務傳遞機制。
在《分散式事務綜述》一中介紹過,XA 協議通過每個 RM(Resource Manager,資源管理器)的本地事務隔離性來保證全域性隔離,並且需要通過序列化隔離級別來保證分散式事務一致性。但是,序列化隔離級別存在一定的效能問題,如下所示:
在序列化隔離級別下,會為本來不加鎖的 Select 快照讀操作都加上讀鎖,導致鎖持有時間增加,併發效能進一步降低。當實現了無鎖的全域性一致性讀取以後,比如分散式 MVCC,可以大幅減少鎖持有時間,併發效能會獲得較大提升。
但是不管怎麼優化實現,分散式事務的熱點資料併發效能最高就是趨近於單機本地事務。所以,無論是基於 XA 協議實現的分散式事務,還是單機本地事務,都是存在熱點資料併發效能極限的。
那麼 XA 協議最大的作用是什麼呢?其最大的作用在於資料庫資源橫向擴充套件時,能保證多資源訪問的事務屬性。
當單臺 RM 機器達到資源效能瓶頸,無法滿足業務增長需求時,就需要橫向擴充套件 RM 資源,形成 RM 叢集。通過橫向擴充套件資源,提升非熱點資料的併發效能,這對於大體量的網際網路產品來說,是至關重要的。
以上圖為例,假設單臺 RM 的非熱點資料併發效能為 100 TPS,那麼 5臺 RM 就是 500 TPS,就算一個分散式事務平均涉及 2 臺 RM,也有 250 TPS,提升了 2.5 倍的非熱點併發能力。
綜上所述,基於 XA 協議實現的分散式事務並不能提升熱點併發效能,其意義在於橫向擴充套件資源提升非熱點資料併發效能時,能嚴格保證對多資源訪問的事務 ACID 特性。
至於熱點資料併發效能問題,對於一般的應用來說,經過 SQL 層面一定的效能優化之後,其併發效能基本就能夠滿足業務的需求。如果經過優化,達到效能極限之後,還不能滿足,就需要上升到業務層面,根據業務特點,通過專門的業務邏輯或業務架構優化來實現。
直接在資源層實現分散式事務的另外一點好處是其普適性,可以對上層業務遮蔽底層實現細節。這一點在雲服務時代特別有用,雲服務面對的是大量的中小企業,甚至是個人開發者,業務訴求不盡相同,普適、標準的分散式事務產品是非常有必要的,可以讓開發者從底層技術細節中脫離出來,更專注於業務邏輯的實現,從而獲得更高效、快速的業務發展。
基於 TCC 模型的應用場景
TCC 分散式事務模型直接作用於服務層。不與具體的服務框架耦合,與底層 RPC 協議無關,與底層儲存介質無關,可以靈活選擇業務資源的鎖定粒度,減少資源鎖持有時間,可擴充套件性好,可以說是為獨立部署的 SOA 服務而設計的。
TCC 模型優勢
對於 TCC 分散式事務模型,筆者認為其在業務場景應用上,有兩方面的意義。
1、跨服務的分散式事務
這一部分的作用與 XA 類似,服務的拆分,也可以認為是資源的橫向擴充套件,只不過方向不同而已。
橫向擴充套件可能沿著兩個方向發展:
1. 功能擴充套件。根據功能對資料進行分組,並將不同的功能組分佈在多個不同的資料庫上,這實際上就是 SOA 架構下的服務化。
2. 資料分片,在功能組內部將資料拆分到多個資料庫上,為橫向擴充套件增加一個新的維度。
下圖簡要闡釋了橫向資料擴充套件策略:
橫向擴充套件的兩種方法可以同時進行運用:使用者資訊(Users)、產品資訊(Products)與交易資訊(Trans)三個不同功能組可以儲存在不同的資料庫中。另外,每個功能組內根據其業務量可以再拆分到多個資料庫中,各功能組可以相互獨立地進行擴充套件。
因此,TCC 的其中一個作用就是在按照功能橫向擴充套件資源時,保證多資源訪問的事務屬性。
2、兩階段拆分
TCC 另一個作用就是把兩階段拆分成了兩個獨立的階段,通過資源業務鎖定的方式進行關聯。資源業務鎖定方式的好處在於,既不會阻塞其他事務在第一階段對於相同資源的繼續使用,也不會影響本事務第二階段的正確執行。
XA模型的併發事務
TCC 模型的併發事務
可以發現 TCC 模型進一步減少了資源鎖的持有時間。同時,從理論上來說,只要業務允許,事務的第二階段什麼時候執行都可以,反正資源已經業務鎖定,不會有其他事務動用該事務鎖定的資源。
這對業務有什麼好處呢?拿支付寶的擔保交易場景來說,簡化情況下,只需要涉及兩個服務,交易服務和賬務服務。交易作為主業務服務,賬務作為從業務服務,提供 Try、Commit、Cancel 介面:
1. Try 介面扣除使用者可用資金,轉移到預凍結資金。預凍結資金就是業務鎖定方案,每個事務第二階段只能使用本事務的預凍結資金,在第一階段執行結束後,其他併發事務也可以繼續處理使用者的可用資金。
2. Commit 介面扣除預凍結資金,增加中間賬戶可用資金(擔保交易不能立即把錢打給商戶,需要有一箇中間賬戶來暫存)。
假設只有一箇中間賬戶的情況下,每次呼叫支付服務的 Commit 介面,都會鎖定中間賬戶,中間賬戶存在熱點效能問題。
但是,在擔保交易場景中,七天以後才需要將資金從中間賬戶劃撥給商戶,中間賬戶並不需要對外展示。因此,在執行完支付服務的第一階段後,就可以認為本次交易的支付環節已經完成,並向使用者和商戶返回支付成功的結果,並不需要馬上執行支付服務二階段的 Commit 介面,等到低鋒期時,再慢慢消化,非同步地執行。
可能部分讀者認為擔保交易比較特殊,其實直付交易(直接把錢打到商戶賬戶的交易模式,Commit 介面扣除預凍結資金以後,不是轉移到中間賬務,而是直接轉移到商戶賬戶)也可以這樣使用,只要提前告知商戶,高峰期交易資金不是實時到賬,但保證在一定時間之內結算完成,商戶應該也是可以理解的。
這就是 TCC 分散式事務模型的二階段非同步化功能,從業務服務的第一階段執行成功,主業務服務就可以提交完成,然後再由框架非同步的執行各從業務服務的第二階段。
通用型 TCC 解決方案
通用型 TCC 解決方案就是最典型的 TCC 分散式事務模型實現,所有從業務服務都需要參與到主業務服務的決策當中。
適用場景
由於從業務服務是同步呼叫,其結果會影響到主業務服務的決策,因此通用型 TCC 分散式事務解決方案適用於執行時間確定且較短的業務,比如網際網路金融企業最核心的三個服務:交易、支付、賬務:
當使用者發起一筆交易時,首先訪問交易服務,建立交易訂單;然後交易服務呼叫支付服務為該交易建立支付訂單,執行收款動作,最後支付服務呼叫賬務服務記錄賬戶流水和記賬。
為了保證三個服務一起完成一筆交易,要麼同時成功,要麼同時失敗,可以使用通用型 TCC 解決方案,將這三個服務放在一個分散式事務中,交易作為主業務服務,支付作為從業務服務,賬務作為支付服務的巢狀從業務服務,由 TCC 模型保證事務的原子性。
支付服務的 Try 介面建立支付訂單,開啟巢狀分散式事務,並呼叫賬務服務的 Try 介面;賬務服務在 Try 介面中凍結買家資金。一階段呼叫完成後,交易完成,提交本地事務,由 TCC 框架完成分散式事務各從業務服務二階段的呼叫。
支付服務二階段先呼叫賬務服務的 Confirm 介面,解凍買家資金;增加賣家可用資金。呼叫成功後,支付服務修改支付訂單為完成狀態,完成支付。
當支付和賬務服務二階段都呼叫完成後,整個分散式事務結束。
非同步確保型 TCC 解決方案
非同步確保型 TCC 解決方案的直接從業務服務是可靠訊息服務,而真正的從業務服務則通過訊息服務解耦,作為訊息服務的消費端,非同步地執行。
可靠訊息服務需要提供 Try,Confirm,Cancel 三個介面。Try 介面預傳送,只負責持久化儲存訊息資料;Confirm 介面確認傳送,這時才開始真正的投遞訊息;Cancel 介面取消傳送,刪除訊息資料。
訊息服務的訊息資料獨立儲存,獨立伸縮,降低從業務服務與訊息系統間的耦合,在訊息服務可靠的前提下,實現分散式事務的最終一致性。
此解決方案雖然增加了訊息服務的維護成本,但由於訊息服務代替從業務服務實現了 TCC 介面,從業務服務不需要任何改造,接入成本非常低。
適用場景
由於從業務服務消費訊息是一個非同步的過程,執行時間不確定,可能會導致不一致時間視窗增加。因此,非同步確保性 TCC 分散式事務解決方案只適用於對最終一致性時間敏感度較低的一些被動型業務(從業務服務的處理結果不影響主業務服務的決策,只被動的接收主業務服務的決策結果)。比如會員註冊服務和郵件傳送服務:
當使用者註冊會員成功,需要給使用者傳送一封郵件,告訴使用者註冊成功,並提示使用者啟用該會員。但要注意兩點:
1. 如果使用者註冊成功,一定要給使用者傳送一封郵件;
2. 如果使用者註冊失敗,一定不能給使用者傳送郵件。
因此,這同樣需要會員服務和郵件服務保證原子性,要麼都執行,要麼都不執行。不一樣的是,郵件服務只是一種被動型的業務,並不影響使用者是否能夠註冊成功,它只需要在使用者註冊成功以後傳送郵件給使用者即可,郵件服務不需要參與到會員服務的活動決策中。
對於此種業務場景,可以使用非同步確保型TCC分散式事務解決方案,如下:
由可靠訊息服務來解耦會員和郵件服務,會員服務與訊息服務組成 TCC 事務模型,保證事務原子性。然後通過訊息服務的可靠特性,確保訊息一定能夠被郵件服務消費,從而使得會員與郵件服務在同一個分散式事務中。同時,郵件服務也不會影響會員服務的執行過程,只在會員服務執行成功後被動接收傳送郵件的請求。
補償型 TCC 解決方案
補償型 TCC 解決方案與通用型 TCC 解決方案的結構相似,其從業務服務也需要參與到主業務服務的活動決策當中。但不一樣的是,前者的從業務服務只需要提供 Do 和 Compensate 兩個介面,而後者需要提供三個介面。
Do 介面直接執行真正的完整業務邏輯,完成業務處理,業務執行結果外部可見;Compensate 操作用於業務補償,抵消或部分抵消正向業務操作的業務結果,Compensate操作需滿足冪等性。
與通用型解決方案相比,補償型解決方案的從業務服務不需要改造原有業務邏輯,只需要額外增加一個補償回滾邏輯即可,業務改造量較小。但要注意的是,業務在一階段就執行完整個業務邏輯,無法做到有效的事務隔離,當需要回滾時,可能存在補償失敗的情況,還需要額外的異常處理機制,比如人工介入。
適用場景
由於存在回滾補償失敗的情況,補償型 TCC 分散式事務解決方案只適用於一些併發衝突較少或者需要與外部互動的業務,這些外部業務不屬於被動型業務,其執行結果會影響主業務服務的決策,比如機票代理商的機票預訂服務:
該機票服務提供多程機票預訂服務,可以同時預訂多趟行程航班機票,比如從北京到聖彼得堡,需要第一程從北京到莫斯科,以及第二程從莫斯科到聖彼得堡。
當使用者預訂機票時,肯定希望能同時預訂這兩趟航班的機票,只預訂一趟航班對使用者來說沒有意義。因此,對於這樣的業務服務同樣提出了原子性要求,如果其中一趟航班的機票預訂失敗,另外一趟需要能夠取消預訂。
但是,由於航空公司相對於機票代理商來說屬於外部業務,只提供訂票介面和取消預訂介面,想要推動航空公司改造是極其困難的。因此,對於此類業務服務,可以使用補償型 TCC 分散式事務解決方案,如下:
閘道器服務在原有邏輯基礎上增加 Compensate 介面,負責呼叫對應航空公司的取消預訂介面。
在使用者發起機票預訂請求時,機票服務先通過閘道器 Do 介面,呼叫各航空公司的預訂介面,如果所有航班都預訂成功,則整個分散式事務直接執行成功;一旦某趟航班機票預訂失敗,則分散式事務回滾,由 TCC 事務框架呼叫各閘道器的 Compensate 補償介面,其再呼叫對應航空公司的取消預訂介面。通過這種方式,也可以保證多程機票預訂服務的原子性。
總 結
對於現在的網際網路應用來說,資源橫向擴充套件提供了更多的靈活性,是一種比較容易實現的向外擴充套件方案,但是同時也明顯增加了複雜度,引入一些新的挑戰,比如資源之間的資料一致性問題。
橫向資料擴充套件既可以按資料分片擴充套件,也可以按功能擴充套件。XA 與 TCC 模型在這一點上的作用類似,都能在橫向擴充套件資源的同時,保證多資源訪問的事務屬性,只不過前者作用於資料分片時,後者作用於功能擴充套件時。
XA 模型另外一個意義在於其普適性,拋開效能問題的情況下,幾乎可以適用於所有業務模式,這對於一些基礎性的技術產品來說是非常有用的,比如分散式資料庫、雲服務的分散式事務框架等。
TCC 模型除了跨服務的分散式事務這一層作用之外,還具有兩階段劃分的功能,通過業務資源鎖定,允許第二階段的非同步執行,而非同步化思想正是解決熱點資料併發效能問題的利器之一。
本文結合具體的業務場景和例子,對比分析了各分散式事務解決方案在效能、熱點衝突、接入複雜度和適用場景等方面的能力,希望能幫助各位讀者對分散式事務有更深一層的理解。
業務各有各的不同,有些業務能容忍短期不一致,有些業務的操作可以冪等,無論什麼樣的分散式事務解決方案都有其優缺點,沒有一個銀彈能夠適配所有。因此,業務需要什麼樣的解決方案,還需要結合自身的業務需求、業務特點、技術架構以及各解決方案的特性,綜合分析,才能找到最適合的方案。
下一篇文章將會介紹螞蟻金服在分散式事務上,經過多年發展,服務於內外部大量不同業務,沉澱出的一整套分散式事務產品和多種解決方案。
公眾號:金融級分散式架構(Antfin_SOFA)