微服務(wù)架構(gòu)下,如何克服分布式事務(wù)難題?(微服務(wù)分布式事務(wù)處理)
【摘要】 分布式事務(wù)已經(jīng)成為微服務(wù)落地最大的阻礙,也是最具挑戰(zhàn)性的一個技術(shù)難題。 為此,本文將深入和大家探討微服務(wù)架構(gòu)下,分布式事務(wù)的各種解決方案。
什么是微服務(wù)?微服務(wù)有什么優(yōu)勢和困難?
什么是微服務(wù)架構(gòu)?
簡而言之,微服務(wù)架構(gòu)的系統(tǒng)是一個分布式的系統(tǒng),按業(yè)務(wù)進行劃分為獨立的服務(wù)單元,解決單體系統(tǒng)的不足,同時也滿足越來越復(fù)雜的業(yè)務(wù)需求。每個微服務(wù)僅關(guān)注于完成一件任務(wù)并很好地完成該任務(wù)。
微服務(wù)架構(gòu)的優(yōu)勢
1. 將復(fù)雜的業(yè)務(wù)拆分成多個小的業(yè)務(wù),每個業(yè)務(wù)拆分成一個服務(wù),將復(fù)雜的問題簡單化。利于分工,降低新人的學習成本。
2. 微服務(wù)系統(tǒng)是分布式系統(tǒng),業(yè)務(wù)與業(yè)務(wù)之間完全解耦,隨著業(yè)務(wù)的增加可以根據(jù)業(yè)務(wù)再拆分,具有極強的橫向擴展能力。
3. 服務(wù)間采用 HTTP 協(xié)議通信,服務(wù)與服務(wù)之間完全獨立。每個服務(wù)可以根據(jù)業(yè)務(wù)場景選取合適的編程語言和數(shù)據(jù)庫。
4. 服務(wù)獨立部署,每個服務(wù)的修改和部署對其他服務(wù)沒有影響。
雖然微服務(wù)有以上的優(yōu)勢,但是微服務(wù)實踐仍處于探索階段,很多中小型互聯(lián)網(wǎng)公司,鑒于經(jīng)驗、技術(shù)實力等問題,微服務(wù)落地比較困難。著名架構(gòu)師Chris Richardson指出,目前微服務(wù)主要存如下幾方面困難:
1. 單體應(yīng)用拆分為分布式系統(tǒng)后,進程間的通訊機制和故障處理措施變的更加復(fù)雜。
2. 系統(tǒng)微服務(wù)化后,一個看似簡單的功能,內(nèi)部可能需要調(diào)用多個服務(wù)并操作多個數(shù)據(jù)庫實現(xiàn),服務(wù)調(diào)用的分布式事務(wù)問題變的非常突出。
3. 微服務(wù)數(shù)量眾多,其測試、部署、監(jiān)控等都變的更加困難。
隨著RPC框架的成熟,第一個問題已經(jīng)逐漸得到解決。例如Dubbo可以支持多種通訊協(xié)議,Spring Cloud可以非常好的支持restful調(diào)用。對于第三個問題,隨著Docker、DevOps技術(shù)的發(fā)展以及各公有云PaaS平臺自動化運維工具的推出,微服務(wù)的測試、部署與運維會變得越來越容易。
而對于第二個問題,現(xiàn)在還沒有通用方案很好的解決微服務(wù)產(chǎn)生的事務(wù)問題。分布式事務(wù)已經(jīng)成為微服務(wù)落地最大的阻礙,也是最具挑戰(zhàn)性的一個技術(shù)難題。下面將深入和大家探討微服務(wù)架構(gòu)下,分布式事務(wù)的各種解決方案。
微服務(wù)架構(gòu)下,如何克服分布式事務(wù)難題?
什么是事務(wù)
事務(wù)是由一組SQL語句組成的邏輯處理單元,事務(wù)具有以下4個屬性,通常簡稱為事務(wù)的ACID屬性:
原子性(Atomicity):事務(wù)是一個原子操作單元,其對數(shù)據(jù)的修改,要么全都執(zhí)行,要么全都不執(zhí)行。
一致性(Consistent):在事務(wù)開始和完成時,數(shù)據(jù)都必須保持一致狀態(tài)。這意味著所有相關(guān)的數(shù)據(jù)規(guī)則都必須應(yīng)用于事務(wù)的修改,以保持數(shù)據(jù)的完整性。
隔離性(Isolation):數(shù)據(jù)庫系統(tǒng)提供一定的隔離機制,保證事務(wù)在不受外部并發(fā)操作影響的“獨立”環(huán)境執(zhí)行。數(shù)據(jù)庫事務(wù)隔離級別由低到高依次為Read uncommitted、Read committed、Repeatable 、Serializable。
持久性(Durability):事務(wù)完成之后,它對于數(shù)據(jù)的修改是永久性的,即使出現(xiàn)系統(tǒng)故障也能夠保持。
分布式事務(wù)典型場景:
銀行轉(zhuǎn)賬業(yè)務(wù)是一個典型分布式事務(wù)場景,通常包括以下三種情況:
A. 支行內(nèi)轉(zhuǎn)賬:同一銀行的相同支行內(nèi)轉(zhuǎn)賬
B. 行內(nèi)轉(zhuǎn)賬:同一銀行的不同支行間轉(zhuǎn)賬
C. 跨行轉(zhuǎn)賬:不同銀行的系統(tǒng)進行轉(zhuǎn)賬
對于傳統(tǒng)集中式架構(gòu),A、B通常為本地事務(wù),C為分布式事務(wù)。業(yè)務(wù)微服務(wù)改造后,轉(zhuǎn)入、轉(zhuǎn)出通常為不同的微服務(wù),同一個微服務(wù)也通常運行于不同實例中。A可能變成一個分布式事務(wù),也可能通過一些方法規(guī)避,在本地事務(wù)內(nèi)完成。B和C很難規(guī)避,只能是分布式事務(wù)。
微服務(wù)最佳實踐建議盡量規(guī)避分布式事務(wù),但是在很多業(yè)務(wù)場景(比如上面的B、C轉(zhuǎn)賬場景),分布式事務(wù)是一個繞不開的技術(shù)問題。
分布式事務(wù)常用解決方案
為了解決分布式系統(tǒng)一致性問題,前人在性能和數(shù)據(jù)一致性的反反復(fù)復(fù)權(quán)衡過程中總結(jié)了許多典型的協(xié)議和算法。其中,最常用的是兩階提交協(xié)議(2 Phase Commitment Protocol)。
兩階段提交方案
交易中間件與數(shù)據(jù)庫通過 XA 接口規(guī)范,使用兩階段提交來完成一個全局事務(wù), XA 規(guī)范的基礎(chǔ)是兩階段提交協(xié)議。
第一階段是表決階段,所有參與者都將本事務(wù)能否成功的信息反饋發(fā)給協(xié)調(diào)者;第二階段是執(zhí)行階段,協(xié)調(diào)者根據(jù)所有參與者的反饋,通知所有參與者,步調(diào)一致地在所有分支上提交或者回滾。
兩階段提交方案應(yīng)用非常廣泛,典型商用軟件包括Oracle Tuxedo和IBM CICS。它的優(yōu)點是對業(yè)務(wù)代碼侵入較低,但缺點也很明顯:
性能低下:由于 XA 協(xié)議自身的特點,它會造成事務(wù)資源長時間得不到釋放,鎖定周期長,而且在應(yīng)用層上面無法干預(yù),數(shù)據(jù)并發(fā)沖突高的場景性能很差。
單點問題:協(xié)調(diào)者在整個兩階段提交過程中扮演著舉足輕重的作用,一旦協(xié)調(diào)者所在服務(wù)器宕機,就會影響整個數(shù)據(jù)庫集群的正常運行。比如在第二階段中,如果協(xié)調(diào)者因為故障不能正常發(fā)送事務(wù)提交或回滾通知,那么參與者們將一直處于阻塞狀態(tài)。
同步阻塞:兩階段提交執(zhí)行過程中,所有的參與者都需要聽從協(xié)調(diào)者的統(tǒng)一調(diào)度,期間處于阻塞狀態(tài)而不能從事其他操作,效率及其低下。
因此,兩階段提交方案在互聯(lián)網(wǎng)業(yè)務(wù)中很少使用,無法滿足高并發(fā)需求。
為了這個彌補這種方案帶來性能低的問題,大家又想出了很多種方案來解決,通過在應(yīng)用層做文章,即入侵業(yè)務(wù)的方式,比較典型的是TCC 方案和基于可靠消息的最終一致性方案。
TCC事務(wù)方案
TCC事務(wù)模型在電商、金融領(lǐng)域落地較多。TCC方案其實是兩階段提交的一種改進。其將整個業(yè)務(wù)邏輯的每個分支顯式的分成了Try、Confirm、Cancel三個操作。Try部分完成業(yè)務(wù)的準備工作,confirm部分完成業(yè)務(wù)的提交,cancel部分完成事務(wù)的回滾。基本原理如下圖所示。
事務(wù)開始時,業(yè)務(wù)應(yīng)用會向事務(wù)協(xié)調(diào)器注冊啟動事務(wù)。之后業(yè)務(wù)應(yīng)用會調(diào)用所有服務(wù)的try接口,完成一階段準備。之后事務(wù)協(xié)調(diào)器會根據(jù)try接口返回情況,決定調(diào)用confirm接口或者cancel接口。如果接口調(diào)用失敗,會進行重試。
TCC方案讓應(yīng)用自己定義數(shù)據(jù)庫操作的粒度,使得降低鎖沖突、提高吞吐量成為可能,比如華為分布式事務(wù)中間件DTM性能極高,普通配置服務(wù)器可以支持全局事務(wù)1萬 TPS,分支事務(wù)3萬 TPS。 當然TCC方案也有不足之處,集中表現(xiàn)在以下兩個方面:
業(yè)務(wù)侵入性強。業(yè)務(wù)邏輯的每個分支都需要實現(xiàn)try、confirm、cancel三個操作,應(yīng)用侵入性較強,改造成本高。
實現(xiàn)難度較大。為了滿足一致性的要求,要充分考慮冪等操作,允許重復(fù)執(zhí)行,也要防止資源懸掛,做好并發(fā)訪問控制和數(shù)據(jù)可見性控制等。
上述原因?qū)е耇CC方案大多被研發(fā)實力較強、有迫切需求的大公司所采用。微服務(wù)倡導(dǎo)服務(wù)的輕量化,而TCC方案中很多事務(wù)的處理邏輯需要應(yīng)用自己編碼實現(xiàn),復(fù)雜且開發(fā)量大。
基于消息的最終一致性方案
消息一致性方案是通過消息中間件保證上下游應(yīng)用數(shù)據(jù)操作的一致性?;舅悸肥菍⒈镜夭僮骱桶l(fā)送消息放在一個本地事務(wù)中,保證本地操作和消息發(fā)送要么兩者都成功或者都失敗。下游應(yīng)用向消息系統(tǒng)訂閱該消息,收到消息后執(zhí)行相應(yīng)操作。
消息最終一致方案從本質(zhì)上講是將分布式事務(wù)轉(zhuǎn)換為兩個本地事務(wù),然后依靠下游業(yè)務(wù)的重試機制達到最終一致性。基于消息的最終一致性方案對應(yīng)用侵入性也很高,應(yīng)用需要進行大量業(yè)務(wù)改造,成本非常高。
入侵代碼的方案是基于現(xiàn)有情形“迫不得已”才推出的解決方案,實際上它們實現(xiàn)起來非常不優(yōu)雅,比如TCC,一個事務(wù)的調(diào)用通常伴隨而來的是對該事務(wù)接口增加一系列的反向操作,提交邏輯必然伴隨著回滾的邏輯,這樣的代碼會使得項目非常臃腫,維護成本高。
針對上面所說的分布式事務(wù)解決方案的痛點,很顯然,我們理想的分布式事務(wù)解決方案肯定是性能要好而且要對業(yè)務(wù)無侵入,業(yè)務(wù)層無需關(guān)心分布式事務(wù)機制的約束,做到事務(wù)與業(yè)務(wù)分離,也就是本文所重點推薦的非侵入事務(wù)。
非侵入事務(wù)方案
a. 典型架構(gòu)
非侵入事務(wù)典型架構(gòu)如下圖所示:
事務(wù)核心組件包括:
Transaction Coordinator (TC): 事務(wù)協(xié)調(diào)器,分布式事務(wù)大腦,產(chǎn)生和維護全局事務(wù)、分支事務(wù),推進事務(wù)提交與回滾的二階段處理。TC Server以集群形式提供事務(wù)協(xié)調(diào)能力。
Transaction Manager (TM): 定義全局事務(wù)的邊界,與事務(wù)協(xié)調(diào)器通信以開啟、提交或回滾全局事務(wù)。
Resource Manager (RM): 資源管理器,管理分支事務(wù)處理的資源,與事務(wù)協(xié)調(diào)器通信以開啟、結(jié)束事務(wù)分支,并接收事務(wù)協(xié)調(diào)器指令完成二階段分支事務(wù)提交或回滾。
Lock Server (LS): 分布式鎖服務(wù)器,可以通過它對進行中的分布式事務(wù)所操作的資源查詢、加鎖、放鎖。
一個分布式事務(wù)稱為一個全局事務(wù),下面掛若干個分支事務(wù),一個分支事務(wù)是一個滿足 ACID 的本地事務(wù)。非侵入事務(wù)的核心思想是資源管理器攔截業(yè)務(wù)SQL,對其解析并做額外的一些數(shù)據(jù)處理,產(chǎn)生undo log并保存,一旦發(fā)生全局事務(wù)回滾,通過各個分支事務(wù)對應(yīng)的undo log完成所有分支事務(wù)回滾。
大家很容易想到,兩個全局事務(wù)并行修改了相同數(shù)據(jù),可能會造成根據(jù)undo log完成回滾產(chǎn)生數(shù)據(jù)錯誤。解決的方法是通過Lock Server對事務(wù)所修改數(shù)據(jù)加鎖,全局事務(wù)提交后立即放鎖,全局事務(wù)回滾則等待分支事務(wù)回滾完成放鎖。
b. 典型流程
典型分布式事務(wù)主要執(zhí)行步驟如下:
1. TM請求TC開始新的全局事務(wù),TC創(chuàng)建全局事務(wù)并返回全局事務(wù)ID(XID)。
2. 根據(jù)XID構(gòu)建事務(wù)上下文,通過微服務(wù)的調(diào)用鏈傳播。
3. RM發(fā)現(xiàn)自己處于事務(wù)上下文,得到全局事務(wù)ID并解析SQL,產(chǎn)生undo log和分布式事務(wù)鎖數(shù)據(jù),請求TC創(chuàng)建分支事務(wù)。
4. TC 通過LS加鎖,加鎖成功后創(chuàng)建分支事務(wù)ID并返回。
5. RM 把分支事務(wù)ID與undo log關(guān)聯(lián),與業(yè)務(wù)原始SQL在一個本地事務(wù)內(nèi)提交。
6. 重復(fù)3~5,為全局事務(wù)范圍內(nèi)的每個本地事務(wù)創(chuàng)建一個分支事務(wù)。
7. 如果全局事務(wù)邊界內(nèi)沒有任何異常,則TM請求TC提交全局事務(wù);如果有異常,則TM請求TC回滾全局事務(wù)。
8. TC標記全局事務(wù)狀態(tài),如果為提交則立即通過LS放鎖。推進XID所對應(yīng)全局事務(wù)下的所有分支事務(wù)進行二階段處理,發(fā)送請求到RM。
9. RM完成分支事務(wù)的提交或回滾,并返回狀態(tài)到TC。
10. TC對完成回滾的分支通過LS放鎖。所有分支完成后,返回全局事務(wù)處理結(jié)果到TM。
二階段事務(wù)處理比較關(guān)鍵,在此重點說明一下。
c. 分支事務(wù)提交
如果全局事務(wù)狀態(tài)為提交,則對每個分支發(fā)起分支提交,流程如下圖所示:
RM收到分支事務(wù)提交請求,先保存分支事務(wù)的ID在隊列中并返回。一個線程定時從隊列中取出一批分支事務(wù)ID,構(gòu)建SQL批量刪除所對應(yīng)的undo log日志。分支事務(wù)提交可以異步批量處理,是因為全局事務(wù)已經(jīng)提交,undo log作為中間狀態(tài)已經(jīng)不再重要,只要定期清理即可。
d. 分支事務(wù)回滾
如果全局事務(wù)狀態(tài)為回滾或超時,則對每個分支發(fā)起分支回滾,流程如下圖所示:
RM收到分支事務(wù)回滾請求,開啟一個本地事務(wù),通過分支ID找到對應(yīng)的undo log,構(gòu)建回滾SQL語句并執(zhí)行,刪除undo log,然后提交本地事務(wù)。如果順利完成,TC收到響應(yīng)后通過LS清理該分支所占用資源。
e. 性能分析
非侵入事務(wù)相比XA兩階段提交一個重要性能優(yōu)勢在于鎖定資源時間更短。實際業(yè)務(wù)中,我們知道絕大多數(shù)事務(wù)狀態(tài)為提交,很少比例為回滾。對于XA來說,無論是提交還是回滾,資源都是在二階段釋放。對本文所介紹的非侵入事務(wù)來說,提交狀態(tài)的全局事務(wù),二階段沒有必要拿鎖,只有少比例的回滾狀態(tài)的全局事務(wù),才需要在二階段放鎖。
非侵入事務(wù)不受限于數(shù)據(jù)庫XA接口,實現(xiàn)完全可控。TC、RM、LS這些關(guān)鍵組件對性能影響很大,良好的設(shè)計、實現(xiàn)可以取得非常高的性能。非侵入式事務(wù)實踐證明,它可以輕松滿足絕大多數(shù)高并發(fā)業(yè)務(wù)場景的性能需求。
典型核心業(yè)務(wù)系統(tǒng)分布式事務(wù)改造實例
華為云Stack為某運營商核心業(yè)務(wù)系統(tǒng)分布式事務(wù)改造,該客戶業(yè)務(wù)在月初充值、扣費業(yè)務(wù)高峰期等常見的并發(fā)場景時,對分布式系統(tǒng)提出挑戰(zhàn):
- 高并發(fā)的分布式事務(wù)訪問賬戶表,XA兩階段提交由于加鎖時間長,嚴重影響業(yè)務(wù)。整體性能要求達1000 TPS,傳統(tǒng)或開源分布式事務(wù)難以滿足高可用性與高性能要求。
- XA事務(wù)與其他數(shù)據(jù)庫操作的一致性問題。需要把XA事務(wù)作為DTM TCC事務(wù)的一個分支,將別的數(shù)據(jù)庫操作是另外的分支。
華為云Stack混合云解決方案分布式事務(wù)中間件DTM通過一系列創(chuàng)新技術(shù),提供高性能、高可用、高可靠、高安全、低侵入、易使用的分布式事務(wù)服務(wù),支持TCC事務(wù)和非侵入事務(wù)兩種模型,助力企業(yè)微服務(wù)化改造,優(yōu)雅地解決分布式系統(tǒng)下數(shù)據(jù)一致性難題。