08.09 RocketMQ 4.3正式發佈,支持分佈式事務

RocketMQ 4.3正式發佈,支持分佈式事務

作者 | 馮嘉

近日,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 理論的提出為分佈式事務的發展指出了一個方向。

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

當前解決方案

2PC/3PC

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

RocketMQ 4.3正式发布,支持分布式事务

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

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

RocketMQ 4.3正式发布,支持分布式事务

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

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

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

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

SAGA

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

(1) Choreography:如下圖所示:

RocketMQ 4.3正式发布,支持分布式事务

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

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

RocketMQ 4.3正式发布,支持分布式事务

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

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

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

  3. 開發測試門檻低。

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

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

TCC

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

RocketMQ 4.3正式发布,支持分布式事务

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

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

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

事務消息

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

RocketMQ 4.3正式发布,支持分布式事务

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

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 事務消息的設計流程同樣借鑑了兩階段提交理論,整體交互流程如下圖所示:

RocketMQ 4.3正式发布,支持分布式事务
  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 兩個內部隊列來存儲事務消息推進狀態,如下圖所示:

RocketMQ 4.3正式发布,支持分布式事务

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

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

RocketMQ 4.3正式发布,支持分布式事务

從用戶側來說,用戶需要分別實現本地事務執行以及本地事務回查方法,因此只需關注本地事務的執行狀態即可;而在 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

今日薦文
RocketMQ 4.3正式发布,支持分布式事务

在硅谷,只有失敗者才朝九晚五

想了解更多微服務架構知識,可訂閱極客時間《微服務架構實踐 160 講》視頻課程,可從 0 到 1 理解主流微服務技術棧組建及架構,掌握搭建微服務架構的核心技能,踏上從程序員到架構師的進階之路。講師楊波,拍拍貸研發總監,具有 eBay、攜程等一線企業架構建設經驗。

戳閱讀原文或掃描下方二維碼,瞭解課程詳情。


分享到:


相關文章: