天天看點

如何實作微服務架構下的分布式事務?

摘要:微服務架構下,如何克服分布式事務難題?

什麼是微服務?微服務有什麼優勢和困難?

什麼是微服務架構?

簡而言之,微服務架構的系統是一個分布式的系統,按業務進行劃分為獨立的服務單元,解決單體系統的不足,同時也滿足越來越複雜的業務需求。每個微服務僅關注于完成一件任務并很好地完成該任務。

微服務架構的優勢

1. 将複雜的業務拆分成多個小的業務,每個業務拆分成一個服務,将複雜的問題簡單化。利于分工,降低新人的學習成本。

2. 微服務系統是分布式系統,業務與業務之間完全解耦,随着業務的增加可以根據業務再拆分,具有極強的橫向擴充能力。

3. 服務間采用 HTTP 協定通信,服務與服務之間完全獨立。每個服務可以根據業務場景選取合适的程式設計語言和資料庫。

4. 服務獨立部署,每個服務的修改和部署對其他服務沒有影響。

雖然微服務有以上的優勢,但是微服務實踐仍處于探索階段,很多中小型網際網路公司,鑒于經驗、技術實力等問題,微服務落地比較困難。著名架構師Chris Richardson指出,目前微服務主要存如下幾方面困難:

1. 單體應用拆分為分布式系統後,程序間的通訊機制和故障處理措施變的更加複雜。

2. 系統微服務化後,一個看似簡單的功能,内部可能需要調用多個服務并操作多個資料庫實作,服務調用的分布式事務問題變的非常突出。

3. 微服務數量衆多,其測試、部署、監控等都變的更加困難。

随着RPC架構的成熟,第一個問題已經逐漸得到解決。例如Dubbo可以支援多種通訊協定,Spring Cloud可以非常好的支援restful調用。對于第三個問題,随着Docker、DevOps技術的發展以及各公有雲PaaS平台自動化運維工具的推出,微服務的測試、部署與運維會變得越來越容易。

而對于第二個問題,現在還沒有通用方案很好的解決微服務産生的事務問題。分布式事務已經成為微服務落地最大的阻礙,也是最具挑戰性的一個技術難題。下面将深入和大家探讨微服務架構下,分布式事務的各種解決方案。

微服務架構下,如何克服分布式事務難題?

什麼是事務

事務是由一組SQL語句組成的邏輯處理單元,事務具有以下4個屬性,通常簡稱為事務的ACID屬性:

原子性(Atomicity):事務是一個原子操作單元,其對資料的修改,要麼全都執行,要麼全都不執行。

一緻性(Consistent):在事務開始和完成時,資料都必須保持一緻狀态。這意味着所有相關的資料規則都必須應用于事務的修改,以保持資料的完整性。

隔離性(Isolation):資料庫系統提供一定的隔離機制,保證事務在不受外部并發操作影響的“獨立”環境執行。資料庫事務隔離級别由低到高依次為Read uncommitted、Read committed、Repeatable 、Serializable。

持久性(Durability):事務完成之後,它對于資料的修改是永久性的,即使出現系統故障也能夠保持。

分布式事務典型場景:

銀行轉賬業務是一個典型分布式事務場景,通常包括以下三種情況:

A. 支行内轉賬:同一銀行的相同支行内轉賬

B. 行内轉賬:同一銀行的不同支行間轉賬

C. 跨行轉賬:不同銀行的系統進行轉賬

對于傳統集中式架構,A、B通常為本地事務,C為分布式事務。業務微服務改造後,轉入、轉出通常為不同的微服務,同一個微服務也通常運作于不同執行個體中。A可能變成一個分布式事務,也可能通過一些方法規避,在本地事務内完成。B和C很難規避,隻能是分布式事務。

微服務最佳實踐建議盡量規避分布式事務,但是在很多業務場景(比如上面的B、C轉賬場景),分布式事務是一個繞不開的技術問題。

分布式事務常用解決方案

為了解決分布式系統一緻性問題,前人在性能和資料一緻性的反反複複權衡過程中總結了許多典型的協定和算法。其中,最常用的是兩階送出協定(2 Phase Commitment Protocol)。

兩階段送出方案

交易中間件與資料庫通過 XA 接口規範,使用兩階段送出來完成一個全局事務, XA 規範的基礎是兩階段送出協定。

第一階段是表決階段,所有參與者都将本事務能否成功的資訊回報發給協調者;第二階段是執行階段,協調者根據所有參與者的回報,通知所有參與者,步調一緻地在所有分支上送出或者復原。

如何實作微服務架構下的分布式事務?

兩階段送出方案應用非常廣泛,典型商用軟體包括Oracle Tuxedo和IBM CICS。它的優點是對業務代碼侵入較低,但缺點也很明顯:

性能低下:由于 XA 協定自身的特點,它會造成事務資源長時間得不到釋放,鎖定周期長,而且在應用層上面無法幹預,資料并發沖突高的場景性能很差。

單點問題:協調者在整個兩階段送出過程中扮演着舉足輕重的作用,一旦協調者所在伺服器當機,就會影響整個資料庫叢集的正常運作。比如在第二階段中,如果協調者因為故障不能正常發送事務送出或復原通知,那麼參與者們将一直處于阻塞狀态。

同步阻塞:兩階段送出執行過程中,所有的參與者都需要聽從協調者的統一排程,期間處于阻塞狀态而不能從事其他操作,效率及其低下。

是以,兩階段送出方案在網際網路業務中很少使用,無法滿足高并發需求。

為了這個彌補這種方案帶來性能低的問題,大家又想出了很多種方案來解決,通過在應用層做文章,即入侵業務的方式,比較典型的是TCC 方案和基于可靠消息的最終一緻性方案。

TCC事務方案

TCC事務模型在電商、金融領域落地較多。TCC方案其實是兩階段送出的一種改進。其将整個業務邏輯的每個分支顯式的分成了Try、Confirm、Cancel三個操作。Try部分完成業務的準備工作,confirm部分完成業務的送出,cancel部分完成事務的復原。基本原理如下圖所示。

如何實作微服務架構下的分布式事務?

事務開始時,業務應用會向事務協調器注冊啟動事務。之後業務應用會調用所有服務的try接口,完成一階段準備。之後事務協調器會根據try接口傳回情況,決定調用confirm接口或者cancel接口。如果接口調用失敗,會進行重試。

TCC方案讓應用自己定義資料庫操作的粒度,使得降低鎖沖突、提高吞吐量成為可能,比如華為分布式事務中間件DTM性能極高,普通配置伺服器可以支援全局事務1萬+ TPS,分支事務3萬+ TPS。 當然TCC方案也有不足之處,集中表現在以下兩個方面:

業務侵入性強。業務邏輯的每個分支都需要實作try、confirm、cancel三個操作,應用侵入性較強,改造成本高。

實作難度較大。為了滿足一緻性的要求,要充分考慮幂等操作,允許重複執行,也要防止資源懸挂,做好并發通路控制和資料可見性控制等。

上述原因導緻TCC方案大多被研發實力較強、有迫切需求的大公司所采用。微服務倡導服務的輕量化,而TCC方案中很多事務的處理邏輯需要應用自己編碼實作,複雜且開發量大。

基于消息的最終一緻性方案

消息一緻性方案是通過消息中間件保證上下遊應用資料操作的一緻性。基本思路是将本地操作和發送消息放在一個本地事務中,保證本地操作和消息發送要麼兩者都成功或者都失敗。下遊應用向消息系統訂閱該消息,收到消息後執行相應操作。

如何實作微服務架構下的分布式事務?

消息最終一緻方案從本質上講是将分布式事務轉換為兩個本地事務,然後依靠下遊業務的重試機制達到最終一緻性。基于消息的最終一緻性方案對應用侵入性也很高,應用需要進行大量業務改造,成本非常高。

入侵代碼的方案是基于現有情形“迫不得已”才推出的解決方案,實際上它們實作起來非常不優雅,比如TCC,一個事務的調用通常伴随而來的是對該事務接口增加一系列的反向操作,送出邏輯必然伴随着復原的邏輯,這樣的代碼會使得項目非常臃腫,維護成本高。

針對上面所說的分布式事務解決方案的痛點,很顯然,我們理想的分布式事務解決方案肯定是性能要好而且要對業務無侵入,業務層無需關心分布式事務機制的限制,做到事務與業務分離,也就是本文所重點推薦的非侵入事務。

非侵入事務方案

a. 典型架構

非侵入事務典型架構如下圖所示:

如何實作微服務架構下的分布式事務?

事務核心元件包括:

Transaction Coordinator (TC): 事務協調器,分布式事務大腦,産生和維護全局事務、分支事務,推進事務送出與復原的二階段處理。TC Server以叢集形式提供事務協調能力。

Transaction Manager (TM): 定義全局事務的邊界,與事務協調器通信以開啟、送出或復原全局事務。

Resource Manager (RM): 資料總管,管理分支事務處理的資源,與事務協調器通信以開啟、結束事務分支,并接收事務協調器指令完成二階段分支事務送出或復原。

Lock Server (LS): 分布式鎖伺服器,可以通過它對進行中的分布式事務所操作的資源查詢、加鎖、放鎖。

一個分布式事務稱為一個全局事務,下面挂若幹個分支事務,一個分支事務是一個滿足 ACID 的本地事務。非侵入事務的核心思想是資料總管攔截業務SQL,對其解析并做額外的一些資料處理,産生undo log并儲存,一旦發生全局事務復原,通過各個分支事務對應的undo log完成所有分支事務復原。

大家很容易想到,兩個全局事務并行修改了相同資料,可能會造成根據undo log完成復原産生資料錯誤。解決的方法是通過Lock Server對事務所修改資料加鎖,全局事務送出後立即放鎖,全局事務復原則等待分支事務復原完成放鎖。

b. 典型流程

典型分布式事務主要執行步驟如下:

1.TM請求TC開始新的全局事務,TC建立全局事務并傳回全局事務ID(XID)。

2.根據XID建構事務上下文,通過微服務的調用鍊傳播。

3.RM發現自己處于事務上下文,得到全局事務ID并解析SQL,産生undo log和分布式事務鎖資料,請求TC建立分支事務。

4.TC 通過LS加鎖,加鎖成功後建立分支事務ID并傳回。

5.RM 把分支事務ID與undo log關聯,與業務原始SQL在一個本地事務内送出。

6.重複3~5,為全局事務範圍内的每個本地事務建立一個分支事務。

7.如果全局事務邊界内沒有任何異常,則TM請求TC送出全局事務;如果有異常,則TM請求TC復原全局事務。

8. TC标記全局事務狀态,如果為送出則立即通過LS放鎖。推進XID所對應全局事務下的所有分支事務進行二階段處理,發送請求到RM。

9.RM完成分支事務的送出或復原,并傳回狀态到TC。

10.TC對完成復原的分支通過LS放鎖。所有分支完成後,傳回全局事務處理結果到TM。

二階段事務處理比較關鍵,在此重點說明一下。

c. 分支事務送出

如果全局事務狀态為送出,則對每個分支發起分支送出,流程如下圖所示:

如何實作微服務架構下的分布式事務?

RM收到分支事務送出請求,先儲存分支事務的ID在隊列中并傳回。一個線程定時從隊列中取出一批分支事務ID,建構SQL批量删除所對應的undo log日志。分支事務送出可以異步批量處理,是因為全局事務已經送出,undo log作為中間狀态已經不再重要,隻要定期清理即可。

d. 分支事務復原

如果全局事務狀态為復原或逾時,則對每個分支發起分支復原,流程如下圖所示:

如何實作微服務架構下的分布式事務?

RM收到分支事務復原請求,開啟一個本地事務,通過分支ID找到對應的undo log,建構復原SQL語句并執行,删除undo log,然後送出本地事務。如果順利完成,TC收到響應後通過LS清理該分支所占用資源。

e. 性能分析

非侵入事務相比XA兩階段送出一個重要性能優勢在于鎖定資源時間更短。實際業務中,我們知道絕大多數事務狀态為送出,很少比例為復原。對于XA來說,無論是送出還是復原,資源都是在二階段釋放。對本文所介紹的非侵入事務來說,送出狀态的全局事務,二階段沒有必要拿鎖,隻有少比例的復原狀态的全局事務,才需要在二階段放鎖。

非侵入事務不受限于資料庫XA接口,實作完全可控。TC、RM、LS這些關鍵元件對性能影響很大,良好的設計、實作可以取得非常高的性能。非侵入式事務實踐證明,它可以輕松滿足絕大多數高并發業務場景的性能需求。

典型核心業務系統分布式事務改造執行個體

華為雲Stack為某營運商核心業務系統分布式事務改造,該客戶業務在月初充值、扣費業務高峰期等常見的并發場景時,對分布式系統提出挑戰:

  • 高并發的分布式事務通路賬戶表,XA兩階段送出由于加鎖時間長,嚴重影響業務。整體性能要求達1000+ TPS,傳統或開源分布式事務難以滿足高可用性與高性能要求。
  • XA事務與其他資料庫操作的一緻性問題。需要把XA事務作為DTM TCC事務的一個分支,将别的資料庫操作是另外的分支。

華為雲Stack混合雲解決方案分布式事務中間件DTM通過一系列創新技術,提供高性能、高可用、高可靠、高安全、低侵入、易使用的分布式事務服務,支援TCC事務和非侵入事務兩種模型,助力企業微服務化改造,優雅地解決分布式系統下資料一緻性難題。

點選關注,第一時間了解華為雲新鮮技術~