分佈式事務解決方案與適用場景分析

原創聲明:本文系做者原創,謝絕我的、媒體、公衆號或網站未經受權轉載,違者追究其法律責任。

基於 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 分佈式事務模型,筆者認爲其在業務場景應用上,有兩方面的意義。

一、跨服務的分佈式事務

這一部分的做用與 XA 相似,服務的拆分,也能夠認爲是資源的橫向擴展,只不過方向不一樣而已。

橫向擴展可能沿着兩個方向發展:
1. 功能擴展。根據功能對數據進行分組,並將不一樣的功能組分佈在多個不一樣的數據庫上,這實際上就是 SOA 架構下的服務化。
2. 數據分片,在功能組內部將數據拆分到多個數據庫上,爲橫向擴展增長一個新的維度。

下圖簡要闡釋了橫向數據擴展策略:
橫向擴展的兩種方法能夠同時進行運用:用戶信息(Users)、產品信息(Products)與交易信息(Trans)三個不一樣功能組能夠存儲在不一樣的數據庫中。另外,每一個功能組內根據其業務量能夠再拆分到多個數據庫中,各功能組能夠相互獨立地進行擴展。
所以,TCC 的其中一個做用就是在按照功能橫向擴展資源時,保證多資源訪問的事務屬性。

二、兩階段拆分

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)
相關文章
相關標籤/搜索