阿里P8架构师谈:分布式事务的解决方案,以及原理、总结
分布式事務(wù)是企業(yè)集成中的一個(gè)技術(shù)難點(diǎn),也是每一個(gè)分布式系統(tǒng)架構(gòu)中都會(huì)涉及到的一個(gè)東西,特別是在這幾年越來(lái)越火的微服務(wù)架構(gòu)中,幾乎可以說(shuō)是無(wú)法避免,本文就圍繞分布式事務(wù)各方面與大家進(jìn)行介紹。
事務(wù)
1.1 什么是事務(wù)
數(shù)據(jù)庫(kù)事務(wù)(簡(jiǎn)稱:事務(wù),Transaction)是指數(shù)據(jù)庫(kù)執(zhí)行過(guò)程中的一個(gè)邏輯單位,由一個(gè)有限的數(shù)據(jù)庫(kù)操作序列構(gòu)成。
事務(wù)擁有以下四個(gè)特性,習(xí)慣上被稱為ACID特性:
- 原子性(Atomicity):事務(wù)作為一個(gè)整體被執(zhí)行,包含在其中的對(duì)數(shù)據(jù)庫(kù)的操作要么全部被執(zhí)行,要么都不執(zhí)行。
- 一致性(Consistency):事務(wù)應(yīng)確保數(shù)據(jù)庫(kù)的狀態(tài)從一個(gè)一致?tīng)顟B(tài)轉(zhuǎn)變?yōu)榱硪粋€(gè)一致?tīng)顟B(tài)。一致?tīng)顟B(tài)是指數(shù)據(jù)庫(kù)中的數(shù)據(jù)應(yīng)滿足完整性約束。除此之外,一致性還有另外一層語(yǔ)義,就是事務(wù)的中間狀態(tài)不能被觀察到(這層語(yǔ)義也有說(shuō)應(yīng)該屬于原子性)。
- 隔離性(Isolation):多個(gè)事務(wù)并發(fā)執(zhí)行時(shí),一個(gè)事務(wù)的執(zhí)行不應(yīng)影響其他事務(wù)的執(zhí)行,如同只有這一個(gè)操作在被數(shù)據(jù)庫(kù)所執(zhí)行一樣。
- 持久性(Durability):已被提交的事務(wù)對(duì)數(shù)據(jù)庫(kù)的修改應(yīng)該永久保存在數(shù)據(jù)庫(kù)中。在事務(wù)結(jié)束時(shí),此操作將不可逆轉(zhuǎn)。
1.2 本地事務(wù)
起初,事務(wù)僅限于對(duì)單一數(shù)據(jù)庫(kù)資源的訪問(wèn)控制:
架構(gòu)服務(wù)化以后,事務(wù)的概念延伸到了服務(wù)中。倘若將一個(gè)單一的服務(wù)操作作為一個(gè)事務(wù),那么整個(gè)服務(wù)操作只能涉及一個(gè)單一的數(shù)據(jù)庫(kù)資源:
這類(lèi)基于單個(gè)服務(wù)單一數(shù)據(jù)庫(kù)資源訪問(wèn)的事務(wù),被稱為本地事務(wù)(Local Transaction)。
分布式事務(wù)
本地事務(wù)主要限制在單個(gè)會(huì)話內(nèi),不涉及多個(gè)數(shù)據(jù)庫(kù)資源。但是在基于SOA(Service-Oriented Architecture,面向服務(wù)架構(gòu))的分布式應(yīng)用環(huán)境下,越來(lái)越多的應(yīng)用要求對(duì)多個(gè)數(shù)據(jù)庫(kù)資源,多個(gè)服務(wù)的訪問(wèn)都能納入到同一個(gè)事務(wù)當(dāng)中,分布式事務(wù)應(yīng)運(yùn)而生。
最早的分布式事務(wù)應(yīng)用架構(gòu)很簡(jiǎn)單,不涉及服務(wù)間的訪問(wèn)調(diào)用,僅僅是服務(wù)內(nèi)操作涉及到對(duì)多個(gè)數(shù)據(jù)庫(kù)資源的訪問(wèn)。
當(dāng)一個(gè)服務(wù)操作訪問(wèn)不同的數(shù)據(jù)庫(kù)資源,又希望對(duì)它們的訪問(wèn)具有事務(wù)特性時(shí),就需要采用分布式事務(wù)來(lái)協(xié)調(diào)所有的事務(wù)參與者。
對(duì)于上面介紹的分布式事務(wù)應(yīng)用架構(gòu),盡管一個(gè)服務(wù)操作會(huì)訪問(wèn)多個(gè)數(shù)據(jù)庫(kù)資源,但是畢竟整個(gè)事務(wù)還是控制在單一服務(wù)的內(nèi)部。如果一個(gè)服務(wù)操作需要調(diào)用另外一個(gè)服務(wù),這時(shí)的事務(wù)就需要跨越多個(gè)服務(wù)了。在這種情況下,起始于某個(gè)服務(wù)的事務(wù)在調(diào)用另外一個(gè)服務(wù)的時(shí)候,需要以某種機(jī)制流轉(zhuǎn)到另外一個(gè)服務(wù),從而使被調(diào)用的服務(wù)訪問(wèn)的資源也自動(dòng)加入到該事務(wù)當(dāng)中來(lái)。下圖反映了這樣一個(gè)跨越多個(gè)服務(wù)的分布式事務(wù):
如果將上面這兩種場(chǎng)景(一個(gè)服務(wù)可以調(diào)用多個(gè)數(shù)據(jù)庫(kù)資源,也可以調(diào)用其他服務(wù))結(jié)合在一起,對(duì)此進(jìn)行延伸,整個(gè)分布式事務(wù)的參與者將會(huì)組成如下圖所示的樹(shù)形拓?fù)浣Y(jié)構(gòu)。在一個(gè)跨服務(wù)的分布式事務(wù)中,事務(wù)的發(fā)起者和提交均系同一個(gè),它可以是整個(gè)調(diào)用的客戶端,也可以是客戶端最先調(diào)用的那個(gè)服務(wù)。
較之基于單一數(shù)據(jù)庫(kù)資源訪問(wèn)的本地事務(wù),分布式事務(wù)的應(yīng)用架構(gòu)更為復(fù)雜。
在不同的分布式應(yīng)用架構(gòu)下,實(shí)現(xiàn)一個(gè)分布式事務(wù)要考慮的問(wèn)題并不完全一樣,比如對(duì)多資源的協(xié)調(diào)、事務(wù)的跨服務(wù)傳播等,實(shí)現(xiàn)機(jī)制也是復(fù)雜多變。盡管有這么多工程細(xì)節(jié)需要考慮,但分布式事務(wù)最核心的還是其 ACID 特性。因此,想要了解一個(gè)分布式事務(wù),就先從了解它是怎么實(shí)現(xiàn)事務(wù) ACID 特性開(kāi)始。
下文將從兩個(gè)最常見(jiàn)的分布式事務(wù)模型入手,著重分析分布式事務(wù)的基礎(chǔ)共通點(diǎn),即如何保證分布式事務(wù)的 ACID 特性。
常見(jiàn)的分布式事務(wù)解決方案
1.基于XA協(xié)議的兩階段提交
XA是一個(gè)分布式事務(wù)協(xié)議,由Tuxedo提出。XA中大致分為兩部分:事務(wù)管理器和本地資源管理器。其中本地資源管理器往往由數(shù)據(jù)庫(kù)實(shí)現(xiàn),比如Oracle、DB2這些商業(yè)數(shù)據(jù)庫(kù)都實(shí)現(xiàn)了XA接口,而事務(wù)管理器作為全局的調(diào)度者,負(fù)責(zé)各個(gè)本地資源的提交和回滾。XA實(shí)現(xiàn)分布式事務(wù)的原理如下:
總的來(lái)說(shuō),XA協(xié)議比較簡(jiǎn)單,而且一旦商業(yè)數(shù)據(jù)庫(kù)實(shí)現(xiàn)了XA協(xié)議,使用分布式事務(wù)的成本也比較低。但是,XA也有致命的缺點(diǎn),那就是性能不理想,特別是在交易下單鏈路,往往并發(fā)量很高,XA無(wú)法滿足高并發(fā)場(chǎng)景。XA目前在商業(yè)數(shù)據(jù)庫(kù)支持的比較理想,在mysql數(shù)據(jù)庫(kù)中支持的不太理想,mysql的XA實(shí)現(xiàn),沒(méi)有記錄prepare階段日志,主備切換回導(dǎo)致主庫(kù)與備庫(kù)數(shù)據(jù)不一致。許多nosql也沒(méi)有支持XA,這讓XA的應(yīng)用場(chǎng)景變得非常狹隘。
2.消息事務(wù)+最終一致性
所謂的消息事務(wù)就是基于消息中間件的兩階段提交,本質(zhì)上是對(duì)消息中間件的一種特殊利用,它是將本地事務(wù)和發(fā)消息放在了一個(gè)分布式事務(wù)里,保證要么本地操作成功成功并且對(duì)外發(fā)消息成功,要么兩者都失敗,開(kāi)源的RocketMQ就支持這一特性,具體原理如下:
1、A系統(tǒng)向消息中間件發(fā)送一條預(yù)備消息
2、消息中間件保存預(yù)備消息并返回成功
3、A執(zhí)行本地事務(wù)
4、A發(fā)送提交消息給消息中間件
通過(guò)以上4步完成了一個(gè)消息事務(wù)。對(duì)于以上的4個(gè)步驟,每個(gè)步驟都可能產(chǎn)生錯(cuò)誤,下面一一分析:
- 步驟一出錯(cuò),則整個(gè)事務(wù)失敗,不會(huì)執(zhí)行A的本地操作
- 步驟二出錯(cuò),則整個(gè)事務(wù)失敗,不會(huì)執(zhí)行A的本地操作
- 步驟三出錯(cuò),這時(shí)候需要回滾預(yù)備消息,怎么回滾?答案是A系統(tǒng)實(shí)現(xiàn)一個(gè)消息中間件的回調(diào)接口,消息中間件會(huì)去不斷執(zhí)行回調(diào)接口,檢查A事務(wù)執(zhí)行是否執(zhí)行成功,如果失敗則回滾預(yù)備消息
- 步驟四出錯(cuò),這時(shí)候A的本地事務(wù)是成功的,那么消息中間件要回滾A嗎?答案是不需要,其實(shí)通過(guò)回調(diào)接口,消息中間件能夠檢查到A執(zhí)行成功了,這時(shí)候其實(shí)不需要A發(fā)提交消息了,消息中間件可以自己對(duì)消息進(jìn)行提交,從而完成整個(gè)消息事務(wù)
基于消息中間件的兩階段提交往往用在高并發(fā)場(chǎng)景下,將一個(gè)分布式事務(wù)拆成一個(gè)消息事務(wù)(A系統(tǒng)的本地操作+發(fā)消息)+B系統(tǒng)的本地操作,其中B系統(tǒng)的操作由消息驅(qū)動(dòng),只要消息事務(wù)成功,那么A操作一定成功,消息也一定發(fā)出來(lái)了,這時(shí)候B會(huì)收到消息去執(zhí)行本地操作,如果本地操作失敗,消息會(huì)重投,直到B操作成功,這樣就變相地實(shí)現(xiàn)了A與B的分布式事務(wù)。原理如下:
雖然上面的方案能夠完成A和B的操作,但是A和B并不是嚴(yán)格一致的,而是最終一致的,我們?cè)谶@里犧牲了一致性,換來(lái)了性能的大幅度提升。當(dāng)然,這種玩法也是有風(fēng)險(xiǎn)的,如果B一直執(zhí)行不成功,那么一致性會(huì)被破壞,具體要不要玩,還是得看業(yè)務(wù)能夠承擔(dān)多少風(fēng)險(xiǎn)。
3.TCC 模型
TCC(Try-Confirm-Cancel)分布式事務(wù)模型相對(duì)于 XA 等傳統(tǒng)模型,其特征在于它不依賴資源管理器(RM)對(duì)分布式事務(wù)的支持,而是通過(guò)對(duì)業(yè)務(wù)邏輯的分解來(lái)實(shí)現(xiàn)分布式事務(wù)。
TCC 模型認(rèn)為對(duì)于業(yè)務(wù)系統(tǒng)中一個(gè)特定的業(yè)務(wù)邏輯,其對(duì)外提供服務(wù)時(shí),必須接受一些不確定性,即對(duì)業(yè)務(wù)邏輯初步操作的調(diào)用僅是一個(gè)臨時(shí)性操作,調(diào)用它的主業(yè)務(wù)服務(wù)保留了后續(xù)的取消權(quán)。如果主業(yè)務(wù)服務(wù)認(rèn)為全局事務(wù)應(yīng)該回滾,它會(huì)要求取消之前的臨時(shí)性操作,這就對(duì)應(yīng)從業(yè)務(wù)服務(wù)的取消操作。而當(dāng)主業(yè)務(wù)服務(wù)認(rèn)為全局事務(wù)應(yīng)該提交時(shí),它會(huì)放棄之前臨時(shí)性操作的取消權(quán),這對(duì)應(yīng)從業(yè)務(wù)服務(wù)的確認(rèn)操作。每一個(gè)初步操作,最終都會(huì)被確認(rèn)或取消。
因此,針對(duì)一個(gè)具體的業(yè)務(wù)服務(wù),TCC 分布式事務(wù)模型需要業(yè)務(wù)系統(tǒng)提供三段業(yè)務(wù)邏輯:
初步操作 Try:完成所有業(yè)務(wù)檢查,預(yù)留必須的業(yè)務(wù)資源。
確認(rèn)操作 Confirm:真正執(zhí)行的業(yè)務(wù)邏輯,不作任何業(yè)務(wù)檢查,只使用 Try 階段預(yù)留的業(yè)務(wù)資源。因此,只要 Try 操作成功,Confirm 必須能成功。另外,Confirm 操作需滿足冪等性,保證一筆分布式事務(wù)有且只能成功一次。
取消操作 Cancel:釋放 Try 階段預(yù)留的業(yè)務(wù)資源。同樣的,Cancel 操作也需要滿足冪等性。
TCC 分布式事務(wù)模型包括三部分:
1.主業(yè)務(wù)服務(wù):主業(yè)務(wù)服務(wù)為整個(gè)業(yè)務(wù)活動(dòng)的發(fā)起方,服務(wù)的編排者,負(fù)責(zé)發(fā)起并完成整個(gè)業(yè)務(wù)活動(dòng)。
2.從業(yè)務(wù)服務(wù):從業(yè)務(wù)服務(wù)是整個(gè)業(yè)務(wù)活動(dòng)的參與方,負(fù)責(zé)提供 TCC 業(yè)務(wù)操作,實(shí)現(xiàn)初步操作(Try)、確認(rèn)操作(Confirm)、取消操作(Cancel)三個(gè)接口,供主業(yè)務(wù)服務(wù)調(diào)用。
3.業(yè)務(wù)活動(dòng)管理器:業(yè)務(wù)活動(dòng)管理器管理控制整個(gè)業(yè)務(wù)活動(dòng),包括記錄維護(hù) TCC 全局事務(wù)的事務(wù)狀態(tài)和每個(gè)從業(yè)務(wù)服務(wù)的子事務(wù)狀態(tài),并在業(yè)務(wù)活動(dòng)提交時(shí)調(diào)用所有從業(yè)務(wù)服務(wù)的 Confirm 操作,在業(yè)務(wù)活動(dòng)取消時(shí)調(diào)用所有從業(yè)務(wù)服務(wù)的 Cancel 操作。
一個(gè)完整的 TCC 分布式事務(wù)流程如下:
TCC模型小結(jié)
所謂的TCC編程模式,也是兩階段提交的一個(gè)變種。TCC提供了一個(gè)編程框架,將整個(gè)業(yè)務(wù)邏輯分為三塊:Try、Confirm和Cancel三個(gè)操作。以在線下單為例,Try階段會(huì)去扣庫(kù)存,Confirm階段則是去更新訂單狀態(tài),如果更新訂單失敗,則進(jìn)入Cancel階段,會(huì)去恢復(fù)庫(kù)存??傊?#xff0c;TCC就是通過(guò)代碼人為實(shí)現(xiàn)了兩階段提交,不同的業(yè)務(wù)場(chǎng)景所寫(xiě)的代碼都不一樣,復(fù)雜度也不一樣,因此,這種模式并不能很好地被復(fù)用。
分布式事務(wù)總結(jié)
分布式事務(wù),本質(zhì)上是對(duì)多個(gè)數(shù)據(jù)庫(kù)的事務(wù)進(jìn)行統(tǒng)一控制,按照控制力度可以分為:不控制、部分控制和完全控制。不控制就是不引入分布式事務(wù),部分控制就是各種變種的兩階段提交,包括上面提到的消息事務(wù)+最終一致性、TCC模式,而完全控制就是完全實(shí)現(xiàn)兩階段提交。部分控制的好處是并發(fā)量和性能很好,缺點(diǎn)是數(shù)據(jù)一致性減弱了,完全控制則是犧牲了性能,保障了一致性,具體用哪種方式,最終還是取決于業(yè)務(wù)場(chǎng)景。作為技術(shù)人員,一定不能忘了技術(shù)是為業(yè)務(wù)服務(wù)的,不要為了技術(shù)而技術(shù),針對(duì)不同業(yè)務(wù)進(jìn)行技術(shù)選型也是一種很重要的能力!
你可能也喜歡:
總結(jié)
以上是生活随笔為你收集整理的阿里P8架构师谈:分布式事务的解决方案,以及原理、总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 深度学习在美团推荐平台排序中的运用
- 下一篇: 2019最新拼多多Java面试题:幻影读