1. 程式人生 > >rocketmq 事務訊息

rocketmq 事務訊息

轉自  https://mp.weixin.qq.com/s?__biz=MzU4NzU0MDIzOQ==&mid=2247484003&idx=1&sn=8b9b084f463c6a0bd0ce04d9ca670079&scene=19

近日,Apache RocketMQ 社群正式釋出4.3版本。此次釋出不僅包括提升效能,減少記憶體使用等原有特性增強,還修復了部分社群提出的若干問題,更重要的是該版本開源了社群最為關心的分散式事務訊息,而且實現了對外部元件的零依賴。接下來,本文將詳細探祕RocketMQ事務訊息的設計原理以及實現機制。

 

一、需求緣起

在微服務架構中,隨著服務的逐步拆分,資料庫私有已經成為共識,這也導致所面臨的分散式事務問題成為微服務落地過程中一個非常難以逾越的障礙,但是目前尚沒有一個完整通用的解決方案。

 

其實不僅僅是在微服務架構中,隨著使用者訪問量的逐漸上漲,資料庫甚至是服務的分片、分割槽、水平拆分、垂直拆分已經逐漸成為較為常用的提升瓶頸的解決方案,因此越來越多的原子操作變成了跨庫甚至是跨服務的事務操作。最終結果是在對高效能、高擴充套件性,高可用性的追求的道路上,我們開始逐漸放鬆對一致性的追求,但是在很多場景下,尤其是賬務,電商等業務中,不可避免的存在著一致性問題,使得我們不得不去探尋一種機制,用以在分散式環境中保證事務的一致性。

 

 

二、理論基石

微服務使得單體架構擴充套件為分散式架構,在擴充套件的過程中,逐漸喪失了單體架構中資料來源單一,可以直接依賴於資料庫進行事務操作的能力,而關係型資料庫中,提供了強大的事務處理能力,可以滿足ACID(Atomicity,Consistency,Isolation,Durability)的特性,這種特性保證了資料操作的強一致性,這也是分散式環境中弱一致性以及最終一致性能夠得以實現的基礎。

 

資料一致性分為三個種類型:強一致性,弱一致性以及最終一致性,正如上文所述,資料庫實現的就是強一致性,能夠保證在寫入一份新的資料庫,立即使其可見。最終一致性是弱一致性的強化版,系統保證在沒有後續更新的前提下,系統最終返回上一次更新操作的值。在沒有故障發生的前提下,不一致視窗的時間主要受通訊延遲,系統負載和複製副本的個數影響。

 

然而,微服務作為分散式系統,同樣受CAP[1] 原理的制約,在CAP理論中,

 

C:Consistency

A:Availability

P:Partition tolerance

 

三者不可同時滿足,而服務化中,更多的是提升A以及P,在這個過程中不可避免的會降低對C的要求,因此,BASE理論隨之而來。

 

BASE[2] 理論來源於ebay在2008年ACM中發表的論文,BASE理論的基本原則有三個:Basically Available,Soft state,Eventually consistent,主要目的是為了提升分散式系統的可伸縮性,論文同樣闡述瞭如何對業務進行調整以及折中的手段,BASE理論的提出為分散式事務的發展指出了一個方向。

 

在最終一致性的實現過程中,最基本的操作就是保證事務參與者的冪等性,所謂的冪等性,就是業務方能夠使用相關的手段,保證單個事務多次提交依然能夠保證達到同樣的目的。

 

 

三、當前解決方案

1、2PC/3PC

 

談到分散式事務,首先要說的就是2PC(two phase commit)方案,如下圖所示[3]

 

 

2PC把事務的執行分為兩個階段,第一個階段即prepare階段,這個階段實際上就是投票階段,協調者向參與者確認是否可以共同提交,再得到全部參與者的所有回答後,協調者向所有的參與者釋出共同提交或者共同回滾的指令,用以保證事務達到一致性。     

 

但是分散式系統中的所有通訊均存在著三種狀態:成功,失敗,超時。其中,超時狀態的存在是我們在設計分散式系統時所面對的永遠的痛,2PC同樣存在問題,尤其是在傳送完可以提交的指令後,參與者在沒有收到提交或者回滾的指令時,面對已經上鎖的資源,面對已經寫出去的undo或者redo日誌,參與者會一時陷入手足無措的狀態,為了解決這個問題,3PC應運而生,如下圖所示[4]

 

3PC在commit之前增加了preCommit的過程,使得在參與者在收不到確認時,依然可以從容commit或者rollback,避免資源鎖定太久導致浪費。但是3PC同樣存在著很多問題。實現起來非常複雜,因為很難通過多次詢問來解決系統間分歧問題,尤其是存在超時狀態互不信任的分散式網路中,這也就是著名的拜占庭將軍問題[5]

 

總結一下,2PC是幾乎所有分散式事務演算法的基礎,後續的分散式事務演算法幾乎都由此改進而來,其優缺點非常明顯:

 

» 優點:在於已經有較為成熟的實現方案,比如XA。

 

» 缺點:XA是一個阻塞協議。服務在投票後需要等待協調器的決定,此時服務會阻塞並鎖定資源。由於其阻塞機制和最差時間複雜度高, 因此,這種設計不能適應隨著事務涉及的服務數量增加而擴充套件的需要,很難用於併發較高以及子事務宣告週期較長(long-running transactions)的分散式服務中。

 

2、SAGA

 

SAGA演算法[6] 於1987年提出,是一種非同步的分散式事務解決方案,其理論基礎在於,其假設所有事件按照順序推進,總能達到系統的最終一致性,因此saga需要服務分別定義提交介面以及補償介面,當某個事務分支失敗時,呼叫其它的分支的補償介面來進行回滾,saga的具體實現分為兩種:Choreography以及Orchestration:

 

(1)   Choreography:如下圖所示:

這種模式下不存在協調器的概念,每個節點均對自己的上下游負責,在監聽處理上游節點事件的同時,對下游節點發布事件。

 

(2)Orchestration:存在中心節點的模式,如下圖所示:

該中心節點,即協調器知道整個事務的分佈狀態,相比於無中心節點方式,該方式有著許多優點:

 

1.能夠避免事務之間的迴圈依賴關係。

2.參與者只需要執行命令/回覆(其實回覆訊息也是一種事件訊息),降低參與者的複雜性。

4.開發測試門檻低。

5. 在新增新步驟時,事務複雜性保持線性,回滾更容易管理。因此大多數saga模型實現均採用了這種思路。

 

總結一下:SAGA模型的優點在於其降低了事務粒度,使得事務擴充套件更加容易,同時採用了非同步化方式提升效能。但是其缺點在於很多時候很難定義補償介面,回滾代價高,而且由於SAGA在執行過程中採用了先提交後補償的思路進行操作,所以單個子事務在併發提交時的隔離性很難保證。

 

3、TCC

 

TCC(Try-Confirm-Concel)模型[7] 同樣是一種補償性事務,主要分為Try:檢查、保留資源,Confirm:執行事務,Concel:釋放資源三個階段,如下圖所示:

其中,活動管理器記錄了全域性事務的推進狀態以及各子事務的執行狀態,負責推進各個子事務共同進行提交或者回滾。同時負責在子事務處理超時後不停重試,重試不成功後轉手工處理,用以保證事務的最終一致性。

 

總結一下,相比於SAGA模型,其優點在於嘗試階段僅僅只是對業務系統做檢測,並保留業務資源,並沒有真正提交,所以後續SAGA需要針對提交的事務做補償,而TCC則僅僅需要釋放保留資源,降低了補償成本;並且,由於在Try階段對資源進行了保留鎖定,所以相比於SAGA模式,TCC模式擁有更高的隔離性。

 

缺點:相比於SAGA模式,TCC模式多增加了一個狀態,導致在業務開發過程中,複雜度上升,而且協調器與子事務的通訊過程增加,狀態輪轉處理也更為複雜。

 

 

四、事物訊息

以購物場景為例,張三購買物品,賬戶扣款100元的同時,需要保證在下游的會員服務中給該賬戶增加100積分。由於資料庫私有,所以導致在實際的操作過程中會出現很多問題,比如先發送訊息,可能會因為扣款失敗導致賬戶積分無故增加,如果先執行扣款,則有可能因服務宕機,導致積分不能增加,無論是先發訊息還是先執行本地事務,都有可能導致出現數據不一致的結果。

 

事務訊息的本質就是為了解決此類問題,解決本地事務執行與訊息傳送的原子性問題。目前,事務訊息在多種分散式訊息中介軟體種均有實現,但是其實現方式思路卻各有不同。

 

1、傳統事務訊息實現

 

傳統事務訊息實現,一種思路是依賴於AMQP協議用來確保訊息傳送成功,AMQP模式下需要在傳送在傳送事務訊息時進行兩階段提交,首先進行tx_select開啟事務,然後再進行訊息傳送,最後進行訊息的commit或者是rollback。這個過程可以保證在訊息傳送成功的同時本地事務也一定成功執行,但事務粒度不好控制,而且會導致效能急劇下降,同時依然無法解決本地事務執行與訊息傳送的原子性問題。

 

還有另外一種思路,就是通過保證多條訊息的同時可見性來保證事務一致性。但是此類訊息事務實現機制更多的是用到consume-transform-produce場景中,其本質還是用來保證訊息自身事務,並沒有把外部事務包含進來。

 

2、RocketMQ事務訊息

 

RocketMQ事務訊息設計則主要是為了解決Producer端的訊息傳送與本地事務執行的原子性問題,RocketMQ的設計中broker與producer端的雙向通訊能力,使得broker天生可以作為一個事務協調者存在;而RocketMQ本身提供的儲存機制,則為事務訊息提供了持久化能力;RocketMQ的高可用機制以及可靠訊息設計,則為事務訊息在系統在發生異常時,依然能夠保證事務的最終一致性達成。

 

2.1 RocketMQ 事務訊息設計

事務訊息作為一種非同步確保型事務, 將兩個事務分支通過MQ進行非同步解耦,RocketMQ事務訊息的設計流程同樣借鑑了兩階段提交理論,整體互動流程如下圖所示:

  1. 事務發起方首先發送prepare訊息到MQ。

  2. 在傳送prepare訊息成功後執行本地事務。

  3. 根據本地事務執行結果返回commit或者是rollback。

  4. 如果訊息是rollback,MQ將刪除該prepare訊息不進行下發,如果是commit訊息,MQ將會把這個訊息傳送給consumer端。

  5. 如果執行本地事務過程中,執行端掛掉,或者超時,MQ將會不停的詢問其同組的其它producer來獲取狀態。

  6. Consumer端的消費成功機制有MQ保證。

     

2.2 RocketMQ事務訊息實現

RocketMQ事務訊息在實現上充分利用了RocketMQ本身機制,在實現零依賴的基礎上,同樣實現了高效能、可擴充套件、全非同步等一系列特性。

 

在具體實現上,RocketMQ通過使用Half Topic 以及Operation Topic 兩個內部佇列來儲存事務訊息推進狀態,如下圖所示:

其中,Half Topic對應佇列中存放著prepare訊息,Operation Topic對應的佇列則存放了prepare message對應的commit/rollback訊息,訊息體中則是prepare message對應的offset,服務端通過比對兩個佇列的差值來找到尚未提交的超時事務,進行回查。

 

在具體實現上,事務訊息作為普通訊息的一個應用場景,在實現過程中進行了分層抽象,從而避免了對RocketMQ原有儲存機制的修改,如下圖所示:

從使用者側來說,使用者需要分別實現本地事務執行以及本地事務回查方法,因此只需關注本地事務的執行狀態即可;而在service層,則對事務訊息的兩階段提交進行了抽象,同時針對超時事務實現了回查邏輯,通過不斷掃描當前事務推進狀態,來不斷反向請求Producer端獲取超時事務的執行狀態,在避免事務掛起的同時,也避免了Producer端的單點故障。而在儲存層,RocketMQ通過Bridge封裝了與底層佇列儲存的相關操作,用以操作兩個對應的內部佇列,使用者也可以依賴其它他儲存介質實現自己的service,RocketMQ會通過ServiceProvider載入進來。

 

從上述事務訊息設計中可以看到,RocketMQ事務訊息較好的解決了事務的最終一致性問題,事務發起方僅需要關注本地事務執行以及實現回查介面給出事務狀態判定等實現,而且在上游事務峰值高時,可以通過訊息佇列,避免對下游服務產生過大壓力。

 

事務訊息不僅適用於上游事務對下游事務無依賴的場景,還可以與一些傳統分散式事務架構相結合,而MQ的服務端作為天生的具有高可用能力的協調者,使得我們未來可以基於RocketMQ提供一站式輕量級分散式事務解決方案,用以滿足各種場景下的分散式事務需求。

 

作者介紹:

馮嘉,Apache RocketMQ聯合創始人,Linux OpenMessaging標準創始人。阿里巴巴高階技術專家,帶領團隊、社群打造了中國分散式雲端計算領域第一個Apache頂級開源中介軟體專案,創立分散式訊息領域的國際標準OpenMessaging。

馮嘉作為阿里巴巴 RocketMQ技術負責人,具有豐富的分散式軟體架構、高併發網站設計、效能調優經驗,擁有國內外多項分散式、推薦領域的專利授權。目前專注於大規模分散式系統、分散式訊息引擎、流計算領域,關注 Hbase/Hadoop/Spark/Flink等大資料技術棧。

 

杜恆,阿里巴巴技術專家,Apache RocketMQ核心控,擁有多年分散式系統研發經驗,對Microservice, Messaging,Storage等領域有深刻理解,擁有多年金融領域開發設計經驗。目前專注RocketMQ核心優化以及Messaging生態建設。

 

 

五、參考文獻

[1] https://en.wikipedia.org/wiki/Cap

[2] https://dl.acm.org/citation.cfm?id=1394128

[3] https://en.wikipedia.org/wiki/Two-phase_commit_protocol

[4] https://en.wikipedia.org/wiki/Three-phase_commit_protocol

[5] https://people.eecs.berkeley.edu/~luca/cs174/byzantine.pdf

[6] https://www.cs.cornell.edu/andru/cs711/2002fa/reading/sagas.pdf

[7] https://www.cloud.alipay.com/docs/2/69656