摘要:?近日,Apache RocketMQ 社區(qū)正式發(fā)布4.3版本。此次發(fā)布不僅包括提升性能,減少內(nèi)存使用等原有特性增強,還修復(fù)了部分社區(qū)提出的若干問題,更重要的是該版本開源了社區(qū)最為關(guān)心的分布式事務(wù)消息,而且實現(xiàn)了對外部組件的零依賴。
近日,Apache RocketMQ 社區(qū)正式發(fā)布4.3版本。此次發(fā)布不僅包括提升性能,減少內(nèi)存使用等原有特性增強,還修復(fù)了部分社區(qū)提出的若干問題,更重要的是該版本開源了社區(qū)最為關(guān)心的分布式事務(wù)消息,而且實現(xiàn)了對外部組件的零依賴。接下來,本文將詳細探秘RocketMQ事務(wù)消息的設(shè)計原理以及實現(xiàn)機制。
一、需求緣起
在微服務(wù)架構(gòu)中,隨著服務(wù)的逐步拆分,數(shù)據(jù)庫私有已經(jīng)成為共識,這也導(dǎo)致所面臨的分布式事務(wù)問題成為微服務(wù)落地過程中一個非常難以逾越的障礙,但是目前尚沒有一個完整通用的解決方案。
其實不僅僅是在微服務(wù)架構(gòu)中,隨著用戶訪問量的逐漸上漲,數(shù)據(jù)庫甚至是服務(wù)的分片、分區(qū)、水平拆分、垂直拆分已經(jīng)逐漸成為較為常用的提升瓶頸的解決方案,因此越來越多的原子操作變成了跨庫甚至是跨服務(wù)的事務(wù)操作。最終結(jié)果是在對高性能、高擴展性,高可用性的追求的道路上,我們開始逐漸放松對一致性的追求,但是在很多場景下,尤其是賬務(wù),電商等業(yè)務(wù)中,不可避免的存在著一致性問題,使得我們不得不去探尋一種機制,用以在分布式環(huán)境中保證事務(wù)的一致性。
二、理論基石
微服務(wù)使得單體架構(gòu)擴展為分布式架構(gòu),在擴展的過程中,逐漸喪失了單體架構(gòu)中數(shù)據(jù)源單一,可以直接依賴于數(shù)據(jù)庫進行事務(wù)操作的能力,而關(guān)系型數(shù)據(jù)庫中,提供了強大的事務(wù)處理能力,可以滿足ACID(Atomicity,Consistency,Isolation,Durability)的特性,這種特性保證了數(shù)據(jù)操作的強一致性,這也是分布式環(huán)境中弱一致性以及最終一致性能夠得以實現(xiàn)的基礎(chǔ)。
數(shù)據(jù)一致性分為三個種類型:強一致性,弱一致性以及最終一致性,正如上文所述,數(shù)據(jù)庫實現(xiàn)的就是強一致性,能夠保證在寫入一份新的數(shù)據(jù)庫,立即使其可見。最終一致性是弱一致性的強化版,系統(tǒng)保證在沒有后續(xù)更新的前提下,系統(tǒng)最終返回上一次更新操作的值。在沒有故障發(fā)生的前提下,不一致窗口的時間主要受通信延遲,系統(tǒng)負載和復(fù)制副本的個數(shù)影響。
然而,微服務(wù)作為分布式系統(tǒng),同樣受CAP[1] 原理的制約,在CAP理論中,
C:Consistency
A:Availability
P:Partition tolerance
三者不可同時滿足,而服務(wù)化中,更多的是提升A以及P,在這個過程中不可避免的會降低對C的要求,因此,BASE理論隨之而來。
BASE[2] 理論來源于ebay在2008年ACM中發(fā)表的論文,BASE理論的基本原則有三個:Basically Available,Soft state,Eventually consistent,主要目的是為了提升分布式系統(tǒng)的可伸縮性,論文同樣闡述了如何對業(yè)務(wù)進行調(diào)整以及折中的手段,BASE理論的提出為分布式事務(wù)的發(fā)展指出了一個方向。
在最終一致性的實現(xiàn)過程中,最基本的操作就是保證事務(wù)參與者的冪等性,所謂的冪等性,就是業(yè)務(wù)方能夠使用相關(guān)的手段,保證單個事務(wù)多次提交依然能夠保證達到同樣的目的。
三、當前解決方案
1、2PC/3PC
談到分布式事務(wù),首先要說的就是2PC(two phase commit)方案,如下圖所示[3]:
2PC把事務(wù)的執(zhí)行分為兩個階段,第一個階段即prepare階段,這個階段實際上就是投票階段,協(xié)調(diào)者向參與者確認是否可以共同提交,再得到全部參與者的所有回答后,協(xié)調(diào)者向所有的參與者發(fā)布共同提交或者共同回滾的指令,用以保證事務(wù)達到一致性。
但是分布式系統(tǒng)中的所有通信均存在著三種狀態(tài):成功,失敗,超時。其中,超時狀態(tài)的存在是我們在設(shè)計分布式系統(tǒng)時所面對的永遠的痛,2PC同樣存在問題,尤其是在發(fā)送完可以提交的指令后,參與者在沒有收到提交或者回滾的指令時,面對已經(jīng)上鎖的資源,面對已經(jīng)寫出去的undo或者redo日志,參與者會一時陷入手足無措的狀態(tài),為了解決這個問題,3PC應(yīng)運而生,如下圖所示[4]:
3PC在commit之前增加了preCommit的過程,使得在參與者在收不到確認時,依然可以從容commit或者rollback,避免資源鎖定太久導(dǎo)致浪費。但是3PC同樣存在著很多問題。實現(xiàn)起來非常復(fù)雜,因為很難通過多次詢問來解決系統(tǒng)間分歧問題,尤其是存在超時狀態(tài)互不信任的分布式網(wǎng)絡(luò)中,這也就是著名的拜占庭將軍問題[5]。
總結(jié)一下,2PC是幾乎所有分布式事務(wù)算法的基礎(chǔ),后續(xù)的分布式事務(wù)算法幾乎都由此改進而來,其優(yōu)缺點非常明顯:
? 優(yōu)點:在于已經(jīng)有較為成熟的實現(xiàn)方案,比如XA。?
? 缺點:XA是一個阻塞協(xié)議。服務(wù)在投票后需要等待協(xié)調(diào)器的決定,此時服務(wù)會阻塞并鎖定資源。由于其阻塞機制和最差時間復(fù)雜度高, 因此,這種設(shè)計不能適應(yīng)隨著事務(wù)涉及的服務(wù)數(shù)量增加而擴展的需要,很難用于并發(fā)較高以及子事務(wù)聲明周期較長(long-running transactions)的分布式服務(wù)中。
2、SAGA
SAGA算法[6] 于1987年提出,是一種異步的分布式事務(wù)解決方案,其理論基礎(chǔ)在于,其假設(shè)所有事件按照順序推進,總能達到系統(tǒng)的最終一致性,因此saga需要服務(wù)分別定義提交接口以及補償接口,當某個事務(wù)分支失敗時,調(diào)用其它的分支的補償接口來進行回滾,saga的具體實現(xiàn)分為兩種:Choreography以及Orchestration:
(1) Choreography:如下圖所示:
這種模式下不存在協(xié)調(diào)器的概念,每個節(jié)點均對自己的上下游負責,在監(jiān)聽處理上游節(jié)點事件的同時,對下游節(jié)點發(fā)布事件。
(2)Orchestration:存在中心節(jié)點的模式,如下圖所示:
該中心節(jié)點,即協(xié)調(diào)器知道整個事務(wù)的分布狀態(tài),相比于無中心節(jié)點方式,該方式有著許多優(yōu)點:
能夠避免事務(wù)之間的循環(huán)依賴關(guān)系;
參與者只需要執(zhí)行命令/回復(fù)(其實回復(fù)消息也是一種事件消息),降低參與者的復(fù)雜性;
開發(fā)測試門檻低;
在添加新步驟時,事務(wù)復(fù)雜性保持線性,回滾更容易管理。因此大多數(shù)saga模型實現(xiàn)均采用了這種思路。
總結(jié)一下:SAGA模型的優(yōu)點在于其降低了事務(wù)粒度,使得事務(wù)擴展更加容易,同時采用了異步化方式提升性能。但是其缺點在于很多時候很難定義補償接口,回滾代價高,而且由于SAGA在執(zhí)行過程中采用了先提交后補償?shù)乃悸愤M行操作,所以單個子事務(wù)在并發(fā)提交時的隔離性很難保證。
3、TCC
TCC(Try-Confirm-Concel)模型[7] 同樣是一種補償性事務(wù),主要分為Try:檢查、保留資源,Confirm:執(zhí)行事務(wù),Concel:釋放資源三個階段,如下圖所示:
其中,活動管理器記錄了全局事務(wù)的推進狀態(tài)以及各子事務(wù)的執(zhí)行狀態(tài),負責推進各個子事務(wù)共同進行提交或者回滾。同時負責在子事務(wù)處理超時后不停重試,重試不成功后轉(zhuǎn)手工處理,用以保證事務(wù)的最終一致性。
總結(jié)一下,相比于SAGA模型,其優(yōu)點在于嘗試階段僅僅只是對業(yè)務(wù)系統(tǒng)做檢測,并保留業(yè)務(wù)資源,并沒有真正提交,所以后續(xù)SAGA需要針對提交的事務(wù)做補償,而TCC則僅僅需要釋放保留資源,降低了補償成本;并且,由于在Try階段對資源進行了保留鎖定,所以相比于SAGA模式,TCC模式擁有更高的隔離性。
缺點:相比于SAGA模式,TCC模式多增加了一個狀態(tài),導(dǎo)致在業(yè)務(wù)開發(fā)過程中,復(fù)雜度上升,而且協(xié)調(diào)器與子事務(wù)的通信過程增加,狀態(tài)輪轉(zhuǎn)處理也更為復(fù)雜。
四、事物消息**
以購物場景為例,張三購買物品,賬戶扣款100元的同時,需要保證在下游的會員服務(wù)中給該賬戶增加100積分。由于數(shù)據(jù)庫私有,所以導(dǎo)致在實際的操作過程中會出現(xiàn)很多問題,比如先發(fā)送消息,可能會因為扣款失敗導(dǎo)致賬戶積分無故增加,如果先執(zhí)行扣款,則有可能因服務(wù)宕機,導(dǎo)致積分不能增加,無論是先發(fā)消息還是先執(zhí)行本地事務(wù),都有可能導(dǎo)致出現(xiàn)數(shù)據(jù)不一致的結(jié)果。
事務(wù)消息的本質(zhì)就是為了解決此類問題,解決本地事務(wù)執(zhí)行與消息發(fā)送的原子性問題。目前,事務(wù)消息在多種分布式消息中間件種均有實現(xiàn),但是其實現(xiàn)方式思路卻各有不同。
1、傳統(tǒng)事務(wù)消息實現(xiàn)
傳統(tǒng)事務(wù)消息實現(xiàn),一種思路是依賴于AMQP協(xié)議用來確保消息發(fā)送成功,AMQP模式下需要在發(fā)送在發(fā)送事務(wù)消息時進行兩階段提交,首先進行tx_select開啟事務(wù),然后再進行消息發(fā)送,最后進行消息的commit或者是rollback。這個過程可以保證在消息發(fā)送成功的同時本地事務(wù)也一定成功執(zhí)行,但事務(wù)粒度不好控制,而且會導(dǎo)致性能急劇下降,同時依然無法解決本地事務(wù)執(zhí)行與消息發(fā)送的原子性問題。
還有另外一種思路,就是通過保證多條消息的同時可見性來保證事務(wù)一致性。但是此類消息事務(wù)實現(xiàn)機制更多的是用到consume-transform-produce場景中,其本質(zhì)還是用來保證消息自身事務(wù),并沒有把外部事務(wù)包含進來。
2、RocketMQ事務(wù)消息
RocketMQ事務(wù)消息設(shè)計則主要是為了解決Producer端的消息發(fā)送與本地事務(wù)執(zhí)行的原子性問題,RocketMQ的設(shè)計中broker與producer端的雙向通信能力,使得broker天生可以作為一個事務(wù)協(xié)調(diào)者存在;而RocketMQ本身提供的存儲機制,則為事務(wù)消息提供了持久化能力;RocketMQ的高可用機制以及可靠消息設(shè)計,則為事務(wù)消息在系統(tǒng)在發(fā)生異常時,依然能夠保證事務(wù)的最終一致性達成。
2.1 RocketMQ 事務(wù)消息設(shè)計
事務(wù)消息作為一種異步確保型事務(wù), 將兩個事務(wù)分支通過MQ進行異步解耦,RocketMQ事務(wù)消息的設(shè)計流程同樣借鑒了兩階段提交理論,整體交互流程如下圖所示:
事務(wù)發(fā)起方首先發(fā)送prepare消息到MQ。
在發(fā)送prepare消息成功后執(zhí)行本地事務(wù)。
根據(jù)本地事務(wù)執(zhí)行結(jié)果返回commit或者是rollback。
如果消息是rollback,MQ將刪除該prepare消息不進行下發(fā),如果是commit消息,MQ將會把這個消息發(fā)送給consumer端。
如果執(zhí)行本地事務(wù)過程中,執(zhí)行端掛掉,或者超時,MQ將會不停的詢問其同組的其它producer來獲取狀態(tài)。
Consumer端的消費成功機制有MQ保證。
2.2 RocketMQ事務(wù)消息實現(xiàn)
RocketMQ事務(wù)消息在實現(xiàn)上充分利用了RocketMQ本身機制,在實現(xiàn)零依賴的基礎(chǔ)上,同樣實現(xiàn)了高性能、可擴展、全異步等一系列特性。
在具體實現(xiàn)上,RocketMQ通過使用Half Topic 以及Operation Topic 兩個內(nèi)部隊列來存儲事務(wù)消息推進狀態(tài),如下圖所示:
其中,Half Topic對應(yīng)隊列中存放著prepare消息,Operation Topic對應(yīng)的隊列則存放了prepare message對應(yīng)的commit/rollback消息,消息體中則是prepare message對應(yīng)的offset,服務(wù)端通過比對兩個隊列的差值來找到尚未提交的超時事務(wù),進行回查。
在具體實現(xiàn)上,事務(wù)消息作為普通消息的一個應(yīng)用場景,在實現(xiàn)過程中進行了分層抽象,從而避免了對RocketMQ原有存儲機制的修改,如下圖所示:
從用戶側(cè)來說,用戶需要分別實現(xiàn)本地事務(wù)執(zhí)行以及本地事務(wù)回查方法,因此只需關(guān)注本地事務(wù)的執(zhí)行狀態(tài)即可;而在service層,則對事務(wù)消息的兩階段提交進行了抽象,同時針對超時事務(wù)實現(xiàn)了回查邏輯,通過不斷掃描當前事務(wù)推進狀態(tài),來不斷反向請求Producer端獲取超時事務(wù)的執(zhí)行狀態(tài),在避免事務(wù)掛起的同時,也避免了Producer端的單點故障。而在存儲層,RocketMQ通過Bridge封裝了與底層隊列存儲的相關(guān)操作,用以操作兩個對應(yīng)的內(nèi)部隊列,用戶也可以依賴其它他存儲介質(zhì)實現(xiàn)自己的service,RocketMQ會通過ServiceProvider加載進來。
從上述事務(wù)消息設(shè)計中可以看到,RocketMQ事務(wù)消息較好的解決了事務(wù)的最終一致性問題,事務(wù)發(fā)起方僅需要關(guān)注本地事務(wù)執(zhí)行以及實現(xiàn)回查接口給出事務(wù)狀態(tài)判定等實現(xiàn),而且在上游事務(wù)峰值高時,可以通過消息隊列,避免對下游服務(wù)產(chǎn)生過大壓力。
事務(wù)消息不僅適用于上游事務(wù)對下游事務(wù)無依賴的場景,還可以與一些傳統(tǒng)分布式事務(wù)架構(gòu)相結(jié)合,而MQ的服務(wù)端作為天生的具有高可用能力的協(xié)調(diào)者,使得我們未來可以基于RocketMQ提供一站式輕量級分布式事務(wù)解決方案,用以滿足各種場景下的分布式事務(wù)需求。
作者介紹:
馮嘉,Apache RocketMQ聯(lián)合創(chuàng)始人,Linux OpenMessaging標準創(chuàng)始人。阿里巴巴高級技術(shù)專家,帶領(lǐng)團隊、社區(qū)打造了中國分布式云計算領(lǐng)域第一個Apache頂級開源中間件項目,創(chuàng)立分布式消息領(lǐng)域的國際標準OpenMessaging。
馮嘉作為阿里巴巴 RocketMQ技術(shù)負責人,具有豐富的分布式軟件架構(gòu)、高并發(fā)網(wǎng)站設(shè)計、性能調(diào)優(yōu)經(jīng)驗,擁有國內(nèi)外多項分布式、推薦領(lǐng)域的專利授權(quán)。目前專注于大規(guī)模分布式系統(tǒng)、分布式消息引擎、流計算領(lǐng)域,關(guān)注 Hbase/Hadoop/Spark/Flink等大數(shù)據(jù)技術(shù)棧。
杜恒,阿里巴巴技術(shù)專家,Apache RocketMQ內(nèi)核控,擁有多年分布式系統(tǒng)研發(fā)經(jīng)驗,對Microservice, Messaging,Storage等領(lǐng)域有深刻理解,擁有多年金融領(lǐng)域開發(fā)設(shè)計經(jīng)驗。目前專注RocketMQ內(nèi)核優(yōu)化以及Messaging生態(tài)建設(shè)。
本文為云棲社區(qū)原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。
評論
查看更多