歡迎光臨
每天分享高質量文章

未來架構| 雲原生時代的分佈式事務

導讀:微服務拆分之後,在很多場景,分佈式事務無法避免。而分佈式事務是行業內的一個技術難點,沒有一種完美的方案。分佈式事務有哪些解決方案?又應該如何落地?聽京東數科資料研發負責人張亮講述分佈式事務的點點滴滴。本文適合研發工程師,技術經理,架構師反覆閱讀。
前文提到過,資料庫事務是需要滿足ACID(原子性、一致性、隔離性、持久性)四個特性的。

在單一資料節點中,事務僅限於對單一資料庫資源進行訪問控制,這種事務稱為本地事務。幾乎所有成熟的關係型資料庫都提供了對本地事務的原生支持。但是在基於微服務的分佈式應用環境下,越來越多的應用場景要求將多個服務的訪問以及相對應的資料庫資源納入同一個事務,因此,分佈式事務應運而生。

關係型資料庫雖然對本地事務提供了完美的ACID原生支持。但在分佈式的場景下,它卻成為了系統性能的瓶頸。如何讓資料庫在分佈式場景下滿足ACID特性,或找尋相應的替代方案,是分佈式事務的重點工作內容。

 

  • XA協議

最早的分佈式事務模型是由 X/Open 國際聯盟提出的 X/Open Distributed Transaction Processing(DTP)模型,也稱為XA協議。

XA協議通過一個全域性事務管理器與多個資源管理器進行交互。全域性事務管理器負責管理全域性事務狀態和參與事務的資源,資源管理器則負責具體的資源操作,XA協議與應用程式的關係如圖9-9所示。

XA協議使用兩階段提交來保證分佈式事務的原子性以,它將提交過程分為準備階段和提交/回滾階段。兩階段提交也是XA協議的標準實現。

在準備階段,全域性事務管理器向每個資源管理器發送準備訊息,用於確認本地事務操作成功與否。在提交階段,若全域性事務管理器收到了所有資源管理器回覆的成功訊息,則向每個資源管理器發送提交訊息,否則發送回滾訊息。資源管理器根據接收到的訊息對本地事務進行提交或回滾。圖9-10展示了XA協議的事務流程。

開啟XA全域性事務後,所有子事務會按照本地預設的隔離級別鎖定資源,並記錄undo和redo日誌,然後由TM發起prepare投票,詢問所有子事務是否可以進行提交。當所有子事務反饋的結果為“yes”時,TM再發起commit;若其中任何一個子事務反饋的結果為“no”,TM則發起rollback;如果在prepare階段的反饋結果為yes,而commit的過程中出現宕機等異常,則在節點服務重啟後,可根據XA recover再次進行commit補償,以保證資料的一致性。

基於XA協議實現的分佈式事務對業務的侵入性很弱。它最大的優勢就是對使用方透明,用戶可以像使用本地事務一樣使用基於XA協議的分佈式事務。XA協議能夠嚴格保障事務的ACID特性。

嚴格保障事務的ACID特性是一把雙刃劍。事務執行過程中需要將所需資源全部鎖定,更加適用於執行時間確定的短事務。對於長事務來說,在整個事務進行期間獨占資料將導致依賴熱點資料的業務系統的併發性能明顯衰退。因此,在高併發性能至上的場景中,基於XA協議的分佈式事務並不是最佳選擇。

  • 柔性事務

如果將實現了ACID特性的事務稱為剛性事務的話,那麼基於BASE事務要素的事務則稱為柔性事務。BASE是基本可用(Basically Available)、柔性狀態(Soft state)和最終一致性(Eventually consistent)的縮寫。

* 基本可用保證分佈式事務參與方不一定同時在線。

* 柔性狀態允許系統狀態更新有一定的延時,客戶不一定能夠察覺。

* 最終一致性通常通過訊息可達的方式來保證。

在ACID事務中,對隔離性的要求很高,在事務執行的過程中必須將所有的資源鎖定。柔性事務的理念則是通過業務邏輯將互斥鎖操作從資源層面移至業務層面,通過放寬對強一致性的要求來換取系統吞吐量的提升。

由於在分佈式系統中可能會出現超時重試的情況,因此柔性事務中的操作必須是冪等的,需要通過冪等來避免多次請求所帶來的問題。實現柔性事務的方案主要有最大努力送達、Saga 、TCC和訊息驅動,下麵我們具體來看。

1.最大努力送達

最大努力送達是最簡單的柔性事務方案,它適合用於“對資料庫的操作最終一定能夠成功”的場景,由NewSQL自動記錄執行失敗的SQL,並反覆嘗試,直至執行成功。

使用最大努力送達方案的柔性事務是沒有回滾功能的。這種型別的柔性事務實現起來最為簡單,但是對場景的要求十分苛刻。這種策略的優點是無鎖定資源時間,性能損耗小。缺點是嘗試多次提交失敗後無法回滾,它僅適用於事務最終一定能夠成功的業務場景。因此它是通過對事務回滾功能的妥協來換取性能提升的。

2.Saga

Saga源於Hector Garcaa-Molrna和Kenneth Salem發表的論文Sagas。Saga方案更適合用於長事務場景。Saga模型將一個分佈式事務拆分為多個本地事務,每個本地事務都有相應的執行模塊(Transaction)和補償模塊(Compensation),任和一個本地事務出錯時,都可以通過呼叫相關的補充方法實現事務的最終一致性。

當每個Saga子事務序列 T1,T2,…,Tn都有對應的補償定義C1,C2,…,Cn-1時,Saga系統可以保證如下狀態。

  • 子事務序列可以完成。這是事務的最佳情況,即無須回滾。

  • 或者序列 T1, T2, …, Tx,和Cx, …, C2, C1(其中x小於n)可以完成。這種狀態能夠保證,當回滾發生時補償操作按照正向操作的相反順序依次執行。

Saga模型同時支持正向恢復和逆向恢復。正向恢復是指重試當前失敗的事務,它的實現前提是每個子事務最終都能夠執行成功;逆向恢復則是指在任意一個子事務失敗時補償所有已完成的事務。

顯然,正向恢覆沒有必要提供補償事務,如果在業務中的子事務最終總會成功,那麼正向恢復能夠降低Saga模型的使用複雜度。另外,即使補償事務難以實現,正向恢復也是不錯的選擇。

雖然在理論上來講,補償事務永不失敗。但是在分佈式的世界中,服務器可能會宕機,網絡可能會失敗,資料中心也可能會停電。因此,需要提供故障恢復後的回退機制,比如人工干預機制等。

Saga模型沒有XA協議中的準備階段,因此事務沒有實現隔離性。如果兩個Saga事務同時操作同一資源則會產生更新丟失、臟資料讀取等問題,這時就需要使用Saga作為事務管理機制的應用程式,在應用層面加入資源鎖定的邏輯了。

3.TCC

TCC(Try-Confirm-Cancel)分佈式事務模型通過對業務邏輯進行分解來實現分佈式事務。顧名思義,TCC事務模型需要業務系統提供以下三種業務邏輯。

  • Try:完成業務檢查,預留業務所需的資源。Try操作是整個TCC的精髓,可以靈活選擇業務資源鎖的粒度。

  • Confirm:執行業務邏輯,直接使用Try階段預留的業務資源,無須再次進行業務檢查。

  • Cancel:釋放Try階段預留的業務資源。

TCC模型僅提供兩階段原子提交協議,保證分佈式事務的原子性。事務的隔離交給業務邏輯來實現。TCC 模型的隔離性思想是,通過對業務的改造將對資料庫資源層面加鎖上移至對業務層面加鎖,從而釋放底層資料庫鎖資源,拓寬分佈式事務鎖協議,提高系統的併發性。

雖然在柔性事務中,TCC事務模型的功能最強,但需要應用方負責提供實現Try、Confirm和Cancel操作的三個接口,供事務管理器呼叫,因此業務方改造的成本較高。

以A賬戶向B賬戶匯款100元為例,圖9-11展示了TCC的流程。匯款服務和收款服務需要分別實現Try、Confirm、Cancel這三個接口,併在業務初始化階段將這三個接口的實現註入TCC事務管理器。

  • 匯款服務

— Try:檢查A賬戶的有效性;檢查A賬戶的餘額是否充足;從A賬戶中扣減100元,並將狀態置為“轉賬中”;預留扣減資源,將“從A賬戶向B賬戶轉賬100元”這個事件存入訊息或日誌。

— Confirm:不做任何操作。

— Cancel:A賬戶增加100元;從日誌或訊息中釋放扣減資源。

  • 收款服務

— Try:檢查B賬戶的有效性。

— Confirm:讀取日誌或者訊息,B賬戶增加100元;從日誌或訊息中釋放扣減資源。

— Cancel:不做任何操作。

由此可以看出,TCC模型對業務的侵入性較強,改造的難度較大。

4.訊息驅動

訊息一致性方案是通過訊息中間件保證上下游應用資料操作一致性的。基本思路是,將本地操作和發送訊息放在同一個本地事務中,下游應用從訊息系統訂閱該訊息,收到訊息後執行相應的操作,本質上是依靠訊息的重試機制達到最終一致性的。圖9-12展示了訊息驅動的事務模型。

訊息驅動的缺點是,耦合度高,需要在業務系統中引入訊息中間件,將導致系統複雜度增加。

基於ACID的強一致性事務和基於BASE的最終一致性事務都不是“銀彈”,只有在最適合的場景中才能發揮它們的最大長處。

表9-4詳細對比了分佈式事務之間的區別,可以幫助開發者進行技術選型。由於訊息驅動與業務系統的耦合度較高,因此不列入對比表格。

表9-4 分佈式事務對比

由於應用場景不同,因此需要開發者合理地在性能與功能之間權衡各種分佈式事務。

強一致性的事務與柔性事務的API和功能並不完全相同,因此不能在它們之間自由地透明切換。在開發決策階段,必須要在強一致的事務和柔性事務之間抉擇,因此設計和開發成本大幅增加。

基於XA協議的強一致事務使用起來相對簡單,但是無法很好地應對互聯網的短事務和高併發場景;柔性事務則需要開發者對應用進行改造,接入成本非常高,並且需要開發者自行實現資源鎖定和反向補償。

一味地追求強一致性未必是最合理的解決方案。對於分佈式系統來說,建議使用“外柔內剛”的設計方案。外柔指的是在跨資料分片的情況下使用柔性事務,保證資料最終一致,並且換取最佳性能;內剛則是指在同一資料分片內使用本地事務,以滿足ACID特性。

本文節選自電子工業出版社《未來架構:從服務化到雲原生》第9章,由電子工業出版社博文視點授權。本書對快速演進中的雲原生資料架構、典型分佈式資料庫中間件進行了剖析,重點介紹Service Mesh等新興概念,創新性地提出了Database Mesh的理念,深度揭秘Apache專案——ShardingSphere,精彩內容層出不窮,知識概念全然領先一代。

 

基於篇幅的考慮,部分內容進行了簡化,想瞭解本書全部詳細內容,可以掃二維碼直接購買。

 

本次活動我們採取文章留言送書的活動。在本周末前,留言點贊數最高的前 3 名我們將免費贈送本書!圖書由電子工業出版社博文視點提供。

赞(0)

分享創造快樂