基本概念
事務
由多個計算任務構(gòu)成的一組具有明確邊界的工作集合液南。事務當中可能包括接口訪問踩麦、網(wǎng)絡通信枚赡、數(shù)據(jù)獲取和處理。嚴格的事務實現(xiàn)應該具備具有原子性谓谦、一致性贫橙、隔離性、持久性四個特性反粥。
原子性(Atomicity):一個事務中的任務要么全部完成卢肃,要么全部失敗。沒有中間狀態(tài)才顿。
隔離性(Isolation):不同事務之間的操作互不影響践剂,并發(fā)的事務其中間狀態(tài)對其他事務不可見。
持久性(Durability):事務一旦完成娜膘,則狀態(tài)永久有效逊脯。
一致性(Consistency):事務涉及的資源或者數(shù)據(jù)在事務前后遵循某種約束,事務的完成或失敗不會影響此狀態(tài)竣贪。
分布式事務
在分布式系統(tǒng)中军洼,事務的訪問涉及的資源、參與計算的節(jié)點都部署在不同的節(jié)點上演怎,這種情況下涉及到的事務稱為分布式事務匕争。
從系統(tǒng)整體的架構(gòu)角度看,分布式事務涉及的場景可以分為兩類爷耀。第一類是甘桑,事務本身只涉及單個應用,但是涉及多個數(shù)據(jù)存儲,一筆交易需要訪問多個數(shù)據(jù)存儲才能最終完成跑杭。第二類铆帽,是事務本身涉及多個應用,同時每個應用可能連接著一個或者多個數(shù)據(jù)存儲德谅,一筆交易需要協(xié)同多個獨立的應用訪問多個數(shù)據(jù)存儲最終才能完成爹橱。
一致性
嚴格地講,一致性并不是事務本身的特性窄做±⑶可以看到,一致性所討論的所謂“約束”是隨著業(yè)務場景變化而變化的椭盏。
一致性的保證组砚,除了數(shù)據(jù)庫層面需要有相應的機制以外,應用層面首先需要進行相應的考慮掏颊。例如糟红,對于典型的兩個賬戶轉(zhuǎn)賬的例子,應用需要保證在同一個事物里面分別對轉(zhuǎn)出賬戶和轉(zhuǎn)入賬戶發(fā)起了減少和增加金額的操作蚯舱,如果任何一個缺失改化,即使使用了事務,從業(yè)務角度看也是違反了一致性約束的枉昏。
在應用層面確保了業(yè)務的正確性之后陈肛,再從數(shù)據(jù)庫層面進行審視。還是轉(zhuǎn)賬的例子兄裂,假設某一個數(shù)據(jù)庫的事務支持出現(xiàn)了問題句旱,在一個事務當中發(fā)生某種故障之后,發(fā)現(xiàn)轉(zhuǎn)出賬戶上錢已經(jīng)相應減少晰奖,而轉(zhuǎn)入賬戶上錢并沒有增加谈撒,那么很明顯這里違反了業(yè)務的一致性約束。但仔細辨析后會發(fā)現(xiàn)匾南,從事務本身考慮啃匿,這個場景實際上首先是違反了事務的原子性的,即應該同時完成的任務只完成了一半蛆楞。所以溯乒,這個場景下面,一致性的體現(xiàn)實際上最終是由原子性保證的豹爹。再比如裆悄,考慮同一筆賬戶上同時發(fā)生的兩筆轉(zhuǎn)賬交易,如果A事務扣減100元臂聋,B事務扣減50元光稼,如果兩個事務都提交之后或南,發(fā)現(xiàn)賬戶實際扣減了50元而不是150元,那么很明顯也違反了業(yè)務上的一致性約束艾君。這種情況采够,實際上是由事務的隔離性保證的。
所以腻贰,總的來說吁恍,一致性更多的是數(shù)據(jù)存儲之上的業(yè)務約束保證扒秸。其描述的特性播演,在事務角度是分別有原子性和隔離性兩種特性在不同場景下分別予以保證的。
強一致性與最終一致性
在討論事務的一致性伴奥,尤其是分布式事務的一致性的時候写烤,涉及到了分布式系統(tǒng)和事務這兩個問題范疇,而這兩個問題范疇中對于一致性都各自有定義并且比較難以理解拾徙。如果進行仔細的研究分辨就會發(fā)現(xiàn)洲炊,事務范疇內(nèi)討論的一致性問題和分布式系統(tǒng)范疇內(nèi)所討論的一致性問題并非同一個問題,他們的問題提出場景和相應的解決模型都不相同尼啡。但不幸的是暂衡,這兩個問題經(jīng)常被放在一起討論,并且會進行類比崖瞭,造成了一定的困惑狂巢。
由于兩個問題本身的復雜性和現(xiàn)有常見討論造成的信息混雜,這里不對一致性進行深入的討論书聚。
針對分布式事務涉及到的一致性問題做如下的假設:
- 分布式事務和分布式系統(tǒng)涉及的共識問題是兩個問題唧领。
- 分布式事務所討論的一致性按照普遍的名稱,稱為為強一致性和最終一致性
- 將系統(tǒng)作為整體看待雌续,分布式事務所述強一致性與事務的一致性討論相同的問題斩个,即在事務執(zhí)行前后系統(tǒng)滿足某種業(yè)務約束徘跪。
- 最終一致性是指率翅,在分布式事務提交后,業(yè)務一致性約束可能不會得到立即滿足炼幔,而是會在未來的某個時間點得到滿足鸽心,并且一定會發(fā)生滚局。
典型實現(xiàn)
強一致性實現(xiàn)
Two/Three Phase Commit
兩階段提交協(xié)議,簡寫2PC再悼,是解決分布式系統(tǒng)一致性問題的算法核畴。分布式事務的一些解決方案采用了該協(xié)議。
在兩階段提交協(xié)議中冲九,有兩種角色:
協(xié)調(diào)者 coordinator:在系統(tǒng)中通常只有一個谤草,負責協(xié)調(diào)決策
參與者 cohorts/participants:在系統(tǒng)中有多個跟束,具備實現(xiàn)本地事務的能力
兩階段協(xié)議的流程可以描述如下:
階段一,投票階段
- 協(xié)調(diào)者向所有參與者發(fā)起詢問丑孩,是否可以提交事務
- 每個參與者為參與事務做準備工作冀宴,如鎖定資源、預先分配資源等温学,將結(jié)果記錄日志
- 參與者將事務準備階段的處理結(jié)果返回協(xié)調(diào)者略贮,如果成功,則回應可以提交
階段二仗岖,提交階段
- 協(xié)調(diào)者根據(jù)參與者返回的結(jié)果進行決策逃延,如果全部返回成功則提交事務,如果有任何一個參與者返回失敗轧拄,則回滾事務揽祥。
- 參與者收到協(xié)調(diào)者的通知后執(zhí)行相應的操作,完成事務的最終提交或者回滾檩电。
2PC做出如下假設:
任意節(jié)點間都可以互相通信拄丰。
所有的參與者都保證本地事務能夠成功提交或者回滾,即參與者本身具備本地事務的管理能力俐末。
參與者在第一階段返回結(jié)果前料按,都會將結(jié)果寫入持久化日志,這樣卓箫,即使在這時候節(jié)點發(fā)生故障载矿,投票的結(jié)果也不會丟失。
所有的節(jié)點都不會發(fā)生永久性的故障丽柿,即節(jié)點可以從故障中恢復過來恢准。
從上述2PC的描述中可以看到,協(xié)議本身存在一些缺陷:
- 由于在第一階段需要預先分配或者鎖定資源甫题,導致在后續(xù)整個事務完成前資源都被占用馁筐,從而導致整體并發(fā)性能較低
- 網(wǎng)絡超時問題。在兩個階段中坠非,都有可能發(fā)生網(wǎng)絡超時敏沉。第一階段,如果參與者返回結(jié)果超時炎码,則協(xié)調(diào)者可以認為其失敗盟迟,回滾事務;第二階段潦闲,如果參與者返回最終提交/回滾的結(jié)果超時攒菠,則可以進行重試操作;或者協(xié)調(diào)者可以將其移出集群歉闰,這樣最終數(shù)據(jù)仍舊是一致的辖众;比較麻煩的是卓起,在第二階段,如果協(xié)調(diào)者不能將最終的決策結(jié)果發(fā)送給參與者凹炸,這樣參與者則不知道如何進行下一步動作(決策信息不足)戏阅,這樣陷入了無法決策的尷尬場景。
為了解決兩階段提交中存在的上述問題啤它,提出了三階段提交協(xié)議奕筐,其三個階段分別為:
投票階段:協(xié)調(diào)者向參與者詢問是否可以執(zhí)行提交,參與者返回結(jié)果变骡。
預提交階段:如果所有參與者都返回成功离赫,則協(xié)調(diào)者向所有參與者發(fā)出預提交的指令,參與者不進行真正的提交锣光,但是鎖定響應的資源笆怠,并返回預提交的結(jié)果铝耻。
提交階段:如果所有參與者在預提交階段都返回成功誊爹,則協(xié)調(diào)者發(fā)出最后的的提交指令,參與者執(zhí)行最終的提交動作瓢捉。
與兩階段提交不同的是频丘,在投票階段,參與者不會鎖定資源泡态,這樣就避免了由于該階段資源鎖定導致的性能下降搂漠。在最終的提交階段,如果出現(xiàn)超時問題某弦,由于參與者在預提交階段已經(jīng)收到了成功指令桐汤,可以認為其他所有參與者也同意了這筆提交,則可以直接將狀態(tài)修改為成功靶壮。
DTP與XA
Distributed Transaction Processing(DTP) 是 X/Open開源標準制定組織制定的分布式事務模型怔毛,該模型規(guī)定了由應用程序(Application Program, AP),多個資源管理節(jié)點(Resource Managers, RMs)腾降,以及事務管理節(jié)點(Transaction Manager, TM)構(gòu)成的邏輯架構(gòu)下的分布式事務模型(在此基礎上進行適當?shù)財U展拣度,分布式系統(tǒng)可以由TM Domain構(gòu)成,每個TM Domain由一組獨立的AP, RMs, TM構(gòu)成螃壤;各個TM Domain之間可以構(gòu)成一個全局事務抗果,每個TM Domain包含一個分支事務)。其中AP發(fā)起事務奸晴,由TM協(xié)調(diào)各個RM完成分布式事務冤馏,每個RM具有本地事務的獨立管理能力。下圖是DTP模型的示意圖寄啼。
DTP的事務提交協(xié)議遵循兩階段提交協(xié)議2PC(實際為:two phase commit with presumed rollback)逮光。XA協(xié)議詳細規(guī)定了TM和RM之間雙向交互的接口規(guī)范赘淮。
最終一致性實現(xiàn)
針對子事務進行補償
一階段提交+補償
在Sharding-JDBC中提到了一種結(jié)合一階段提交和補償模式的方案(Sharding-JDBC將其稱為最大努力送達型,為了與后續(xù)采用消息隊列的模式區(qū)分睦霎,這里不采用該名稱)梢卸,該方案示意圖如下:
此模式下,無需引入事務管理器副女,事務的參與方之間各自提交本地事務蛤高,互不影響。由框架在事務之前記錄事務各個參與方涉及的sql語句碑幅,將其寫入與業(yè)務獨立的事務庫戴陡,并且監(jiān)聽各個獨立事務的執(zhí)行結(jié)果,如果某一個發(fā)生失敗沟涨,則進行一定次數(shù)的重試恤批,如果仍舊失敗,則由獨立的異步送達服務后續(xù)讀取并再進行重試執(zhí)行裹赴。
很明顯喜庞,這種模式下有如下假設:事務經(jīng)過一定次數(shù)的重試后最終一定能夠成功。另外棋返,這種模式一個明顯的薄弱環(huán)節(jié)是在整個過程中引入了事務庫延都,如果在事務的執(zhí)行過程中事務庫本身發(fā)生了故障,那么重試機制將無從保障睛竣。
基于消息:可靠消息/最大努力送達
基于最終一致性的思想晰房,一些分布式事務的解決方案通過引進消息服務來進行完成。相關(guān)的實現(xiàn)方案版本較多射沟,這里根據(jù)補償職責歸屬于消息生產(chǎn)者或者消費者進行劃分殊者,分別將其稱為可靠消息和最大努力送達兩種實現(xiàn)模式。
- 可靠消息
可靠消息模式下验夯,事務的補償由消息的生產(chǎn)者負責猖吴,消息的生產(chǎn)者也是業(yè)務的主動方。其模式示意如下:
其步驟概述為:
- 業(yè)務的主動方在同一個本地事務中簿姨,提交業(yè)務數(shù)據(jù)和消息數(shù)據(jù)距误。
- 本地事務提交后,業(yè)務處理服務通過實時消息服務通知業(yè)務的被動方扁位,通知成功后由實時消息服務刪除消息數(shù)據(jù)准潭。
- 如果通知失敗,則由消息回復系統(tǒng)掃描通知失敗的消息域仇,通過消息服務重試通知刑然。
- 業(yè)務被動方接收到消息通知后,進行本地事務處理并提交暇务。
可以看到泼掠,這種模式有一些前提假設:
假定實時消息服務和消息恢復系統(tǒng)不會發(fā)生不可恢復的故障
業(yè)務主動方的業(yè)務流程怔软,不依賴于業(yè)務被動方
被動方應該保證業(yè)務的冪等性
這種模式下,由于事務補償職責由業(yè)務主動方負責择镇,業(yè)務的被動方實施成本低挡逼。但是,對于業(yè)務的主動方來說腻豌,在主要業(yè)務流程之外需要維護事務補償機制家坎,與主要業(yè)務產(chǎn)生了耦合。如下可靠消息實現(xiàn)方案吝梅,消除了這種耦合:
其步驟概述為:
- 業(yè)務主動方在本地事務提交前虱疏,向?qū)嵤┫⒎照埱蟀l(fā)送消息,實時消息服務記錄待發(fā)送消息苏携。
- 請求成功后做瞪,業(yè)務主動方提交本地事務,并且在成功后向?qū)崟r消息服務確認發(fā)送消息右冻。如果本地事務提交失敗装蓬,則取消發(fā)送消息。
- 實時消息服務根據(jù)確認或取消發(fā)送的指令国旷,選擇是否發(fā)送消息矛物。后續(xù)步驟同上述可靠消息。
- 如果業(yè)務主動方未向?qū)崟r消息服務發(fā)送確認或者取消發(fā)送指令跪但,則由消息狀態(tài)確認系統(tǒng)主動發(fā)起查詢,向業(yè)務處理服務查詢消息發(fā)送狀態(tài)峦萎。
相比于第一種實現(xiàn)方案屡久,上述實現(xiàn)額外引入如下成本:
一次事務中,業(yè)務主動方需要與實時消息服務進行兩次交互爱榔。
業(yè)務主動方需要實現(xiàn)消息狀態(tài)確認接口
- 最大努力送達
不同于可靠消息模式被环,最大努力送達模式下,由業(yè)務主動方進行一定次數(shù)的嘗試(最大努力)详幽,最終一致性保證的職責由業(yè)務被動方負責筛欢。這種模式下,業(yè)務被動方的改造成本更高唇聘。
與可靠消息類似版姑,這種模式也要求主動方業(yè)務不依賴于被動方業(yè)務,但需要被動方實現(xiàn)定期校對系統(tǒng)迟郎,定期向主動方發(fā)起查詢剥险,獲取一段時間內(nèi)丟失的消息,進行事務的補償宪肖。
可以看到表制,不管是一階段提交+補償?shù)姆桨富蛘呤腔谙⒌姆桨附∨溃即嬖谝粋€問題,如果補償機制失效(實際工程中不可能保證100%的可用性)么介,那么將會出現(xiàn)業(yè)務的不一致娜遵,這個時候勢必會造成對業(yè)務的影響。針對這種情況壤短,需要考慮在系統(tǒng)中引入持久化記錄或者日志功能記錄所有未完成事務的狀態(tài)魔熏,并且在必要時候需要進行人工干預。
補償事務模式
最終一致性實現(xiàn)面臨的一個問題是如果事務由于某種原因失敗鸽扁,如何恢復資源的問題蒜绽。由于為了提供系統(tǒng)并發(fā)而采用最終一致性,所以在通常的實現(xiàn)中并不會對資源加鎖桶现,這就導致在并發(fā)的場景下躲雅,如果要恢復資源,不能簡單執(zhí)行回滾骡和,因為很可能資源已經(jīng)被其他訪問修改相赁。在另外的一些場景下面,甚至資源不能進行完全對等的反向操作慰于,例如對于某些緊缺資源钮科,用戶在購買后取消訂閱同樣需要付費。
在最終一致性前提下實現(xiàn)分布式式事務婆赠,面臨的一個問題是如果事務由于某種原因失敗绵脯,如何恢復資源的問題。由于為了提供系統(tǒng)并發(fā)而采用最終一致性休里,所以在通常的實現(xiàn)中并不會對資源加鎖蛆挫,這就導致在并發(fā)的場景下,如果要恢復資源妙黍,不能簡單執(zhí)行回滾悴侵,因為很可能資源已經(jīng)被其他訪問修改。在另外的一些場景下面拭嫁,甚至資源不能進行完全對等的反向操作可免,例如對于某些緊缺資源,用戶在購買后取消訂閱同樣需要付費做粤。
為了解決上述問題浇借,需要引入補償事務模式。即需要單獨定義一個操作驮宴,在事務出現(xiàn)可能的失敗之后逮刨,通過執(zhí)行這個補償操作來完成相應的恢復。
需要注意的是,補償操作同樣可能失敗修己,因此為了進行重試操作恢总,所定義的補償動作需要滿足冪等性。最后睬愤,經(jīng)過重試片仿,補償可能由于比較嚴重的故障仍舊不能成功,因此如果需要提供較高的可靠性尤辱,系統(tǒng)可能需要引入日志記錄或者其他功能對失敗的補償進行記錄砂豌,后續(xù)在故障恢復后進行人工干預或者執(zhí)行其他操作。
TCC
TCC即Try Confirm/Cancel的簡稱光督,是一種分布式事務的實現(xiàn)模式阳距,由支付寶公司在2008年提出,并且得到較大范圍的推廣使用结借。下圖是TCC模式的具體描述:
類似于兩階段提交協(xié)議筐摘,TCC將事務的執(zhí)行劃分為兩個階段,如果第一階段Try所有事務的參與者都回復可以執(zhí)行船老,則執(zhí)行Confirm操作進行提交咖熟;如果第一階段Try操作有任意失敗返回,則執(zhí)行Cancel操作取消事務柳畔。兩個階段所執(zhí)行的操作定義如下:
第一階段馍管,Try操作(嘗試執(zhí)行業(yè)務):
- 完成所有業(yè)務檢查(一致性)
- 預留必須的業(yè)務資源
第二階段,Confirm操作(確認執(zhí)行業(yè)務):
- 真正執(zhí)行業(yè)務
- 不作任何業(yè)務檢查
- 只使用Try階段預留的業(yè)務資源
- Confirm操作需要滿足冪等性
第二階段薪韩,Cancel操作(取消執(zhí)行業(yè)務):
- 釋放Try階段預留的業(yè)務資源
- Cancel操作需要滿足冪等性
在上面的描述中确沸,“預留必須的業(yè)務資源”和“真正執(zhí)行業(yè)務”這兩個描述都是比較籠統(tǒng)的。從可以找到的資料來看躬存,這里的描述對應的實際實現(xiàn)是根據(jù)實際業(yè)務場景而變化的张惹。
考慮一個用戶進行某項業(yè)務,然后贈與積分的場景岭洲,這里假設積分是一個單獨服務。從業(yè)務的角度講坎匿,對于向客戶贈予積分盾剩,所謂預留必須的資源來保證后續(xù)的Confirm操作能夠成功,并不需要在數(shù)據(jù)庫層面做什么操作替蔬。一種實現(xiàn)是記錄一下需要增加相應的積分即可告私,例如在表中增加一個字段對要增加的積分值進行記錄。甚至承桥,可以什么都不做驻粟,在最終的Confirm階段再更新或者插入數(shù)據(jù)即可。
再考慮一個在一個分布式的應用中進行轉(zhuǎn)賬的場景。那么在Try階段蜀撑,對于轉(zhuǎn)出賬戶來說挤巡,預留必須的業(yè)務資源意味著需要盡可能保證后續(xù)的Confirm操作能夠成功,如果什么都不做或者僅僅記錄需要扣減的金額酷麦,考慮并發(fā)的場景矿卑,則很可能在后續(xù)的Confirm操作中由于業(yè)務規(guī)則限制而不能操作成功。因此沃饶,需要在轉(zhuǎn)出賬戶上直接扣減相應的金額母廷,在后續(xù)的Confirm階段則無需進行任何實際操作;而如果由于某些異常導致需要取消事務糊肤,在Cancel階段只需要增加響應的金額即可琴昆。
不同于2PC事務的提交與回滾由TM直接協(xié)調(diào)RM完成的方式,TCC模式從應用層面的操作出發(fā)定義分布式事務的兩個階段馆揉,而且不同的階段操作需要從實際業(yè)務出發(fā)實際確定业舍,基本無法使用統(tǒng)一的實現(xiàn)。因此把介,如果采用TCC模式勤讽,需要在應用層面做比較多的工作,如果是項目改造拗踢,則需要在應用層面進行脚牍,這帶來了比較高的開發(fā)成本。
可見巢墅,TCC模式是一個滿足最終一致性的分布式事務實現(xiàn)模式诸狭,綜合借鑒了補償事務模式和兩階段提交思路。其優(yōu)點是在第一階段不鎖定資源君纫,這樣為高并發(fā)提供了保證驯遇;另外,由于兩個階段的操作在應用層面進行實現(xiàn)蓄髓,所以提供較高的業(yè)務靈活性叉庐。相應的,不滿足強一致性会喝、開發(fā)成本較高是其缺點陡叠。
Saga
Saga一詞最早于八十年代晚期由普林斯頓大學針對長事務(Long Lived Transactions)提出,本身實際就是表示一組由多個子事務構(gòu)成的全局事務肢执,這些子事務之間沒有強依賴關(guān)系枉阵。
Saga通過協(xié)調(diào)每個子事務Ti的調(diào)用完成整個事務,通過定義每個子事務Ti對應的補償事務Ci來完成回滾操作预茄。假設一個全局事務應該由T1...Tn構(gòu)成兴溜,當執(zhí)行至第Tm(m<=n)個事務時發(fā)生了異常,則Saga協(xié)調(diào)所有補償事務完成整體回滾操作,從整體上看拙徽,執(zhí)行順序可能是T1...Tm,Cm...C1(這里如果沒有強依賴關(guān)系刨沦,Cm到C1的取消無需嚴格按照T1至Tm的調(diào)用順序進行反向操作)。
Saga的可以分為兩種實現(xiàn)方式:協(xié)調(diào)模式和編排模式斋攀。這兩種模式的實現(xiàn)中都需要引入穩(wěn)定已卷、可靠的消息服務,整體事務的可靠性依賴于消息服務的可用性等級淳蔼。
協(xié)調(diào)模式下侧蘸,各個事務參與方向消息服務發(fā)布自己的子事務成功或者失敗的消息,其他事務參與方對自己感興趣的事務進行訂閱鹉梨,由消息驅(qū)動整個事務的最終完成或者回滾讳癌。
編排模式引入編排器來完成整個事務的調(diào)度,編排器在事務的各個階段發(fā)布消息存皂,由事務參與方消費消息并向編排器返回執(zhí)行結(jié)果晌坤,編排器根據(jù)結(jié)果選擇進行下一階段調(diào)度或者回滾事務。
隔離性缺失及其對策
所有最終一致性的模式下旦袋,由于并發(fā)的全局事務間并不具備隔離性骤菠,即在完成全局事務的最終提交前,其他事務可以看到彼此的中間狀態(tài)(雖然對于本地子事務來說疤孕,是已經(jīng)提交的狀態(tài))商乎。
由于不滿足隔離性,帶來了如下問題:
更新覆蓋:一個事務覆蓋了另一個事務的更新導致業(yè)務異常祭阀。
例如鹉戚,一個下單操作,需要先生成訂單专控,再檢查庫存抹凳,最后完成訂單創(chuàng)建;假設用戶點擊下單后立刻返回并取消了訂單伦腐,那么由于時間的不確定性赢底,執(zhí)行順序可能看起來是:
- 生成訂單,狀態(tài)為CREATING
- 調(diào)用庫存服務柏蘑,檢查庫存是否足夠
- 取消訂單颖系,狀態(tài)修改為CANCELED
- 庫存檢查結(jié)果通過,修改狀態(tài)為CREATED
用戶的意愿是取消訂單辩越,但最終訂單是成功創(chuàng)建的狀態(tài)。
臟讀:一個事務讀取到了另一個事務未提交的狀態(tài)信粮。
例如黔攒,對某個客戶的賬戶,并發(fā)一個退款業(yè)務和一個支取業(yè)務,執(zhí)行順序可能如下排列:
- 退款交易督惰,增加客戶賬戶額度
- 調(diào)用訂單服務不傅,修改訂單狀態(tài)
- 支取交易,檢查額度滿足支取限制赏胚,成功返回
- 訂單狀態(tài)修改失敗访娶,取消增加客戶賬戶額度。
最終退款交易并沒有發(fā)生觉阅,但是成功完成了一筆額度限制之外的支取崖疤,造成了業(yè)務風險。
不可重復讀和幻讀:一個事務在讀取過程中典勇,由于另一個事務對數(shù)據(jù)進行了修改劫哼,兩次讀取到了不一樣的值或者讀取到了不該看到的數(shù)據(jù)。這兩種情況對于業(yè)務本身的危害相對較小割笙。
針對隔離性缺失可能導致的上述問題权烧,可以在設計階段引入一些對應的辦法進行解決。例如伤溉,對于更新覆蓋般码,可以通過增加語義鎖的方式進行,上述示例中可以直接判斷訂單狀態(tài)為CREATING 而不再更新為取消乱顾;對于臟讀問題板祝,可以調(diào)整業(yè)務的執(zhí)行順序,例如將增加額度放在整個退款交易事務的最后執(zhí)行糯耍。對于幻讀問題扔字,可以通過實例化沖突等方式予以解決等等。
綜合比較
綜合上述討論温技,可以看出針對全局事務的解決方案都有各自的特點革为,沒有一個最優(yōu)的方案,需要結(jié)合實際的應用場景選擇合適的模式舵鳞≌痖荩總的來說,有如下特點:
兩階段提交是強一致性實現(xiàn)蜓堕,適合對一致性要求比較高的場景抛虏。但其問題是并發(fā)性能低,在實際的業(yè)務場景中套才,往往要求比較高的并發(fā)性能迂猴,因此極少采用。
除兩階段提交外的其他所有解決方案背伴,都是最終一致性實現(xiàn)沸毁,全局事務不滿足隔離性要求峰髓,部分實現(xiàn)還存在不滿足原子性(子事務補償失敗)的問題息尺。所以在實際應用中需要結(jié)合業(yè)務實際對這些問題考慮響應的解決辦法携兵。
可靠消息、最大努力送達和一階段提交+補償幾個方案搂誉,實現(xiàn)對業(yè)務本身的侵入相對較小徐紧,通過引入主業(yè)務之外的補償服務可以獲取最終一致性。其中一階段提交+補償無需引入額外的中間件炭懊,實現(xiàn)最簡單并级;可靠消息和最大努力送達主要的改造成本分別位于業(yè)務的主動方和被動方,適合交互系統(tǒng)間無法協(xié)同改造的場景凛虽。
TCC和SAGA方案更貼合實際場景死遭,方案更加完善,但不適合存量應用改造凯旋,對業(yè)務侵入性大呀潭。
【REF】
Distributed Transaction Processing Reference Model Version 3.pdf
Distributed Transaction Processing The XA Specification.pdf
分布式系統(tǒng)的事務[https://coolshell.cn/articles/10910.html]
條分縷析分布式:到底什么是一致性?[https://mp.weixin.qq.com/s?__biz=MzA4NTg1MjM0Mg==&mid=2657261779&idx=1&sn=9fb74c24f8863837d584a96536ba8189&scene=21#wechat_redirect]
大規(guī)模SOA系統(tǒng)中的分布事務處理-程立
https://docs.microsoft.com/zh-cn/azure/architecture/patterns/compensating-transaction
分布式事務在Sharding-Sphere中的實現(xiàn)[https://zhuanlan.zhihu.com/p/41446128]
微服務架構(gòu)設計模式-Chris Richardson