高并發(fā)下分布式事務(wù)的解決方案

儒雅程序員
分布式事務(wù)就是一次大的操作由不同的小操作組成,這些小的操作分布在不同的服務(wù)器上,且屬于不同的應(yīng)用,分布式事務(wù)需要保證這些小操作要么全部成功,要么全部失敗。本質(zhì)上來(lái)說(shuō),分布式事務(wù)就是為了保證不同數(shù)據(jù)庫(kù)的數(shù)據(jù)一致性。

1、什么是分布式事務(wù)

分布式事務(wù)就是指事務(wù)的參與者、支持事務(wù)的服務(wù)器、資源服務(wù)器以及事務(wù)管理器分別位于不同的分布式系統(tǒng)的不同節(jié)點(diǎn)之上。以上是百度百科的解釋,簡(jiǎn)單的說(shuō),就是一次大的操作由不同的小操作組成,這些小的操作分布在不同的服務(wù)器上,且屬于不同的應(yīng)用,分布式事務(wù)需要保證這些小操作要么全部成功,要么全部失敗。本質(zhì)上來(lái)說(shuō),分布式事務(wù)就是為了保證不同數(shù)據(jù)庫(kù)的數(shù)據(jù)一致性。

2、分布式事務(wù)的產(chǎn)生的原因

2.1、數(shù)據(jù)庫(kù)分庫(kù)分表

當(dāng)數(shù)據(jù)庫(kù)單表一年產(chǎn)生的數(shù)據(jù)超過(guò)1000W,那么就要考慮分庫(kù)分表,具體分庫(kù)分表的原理在此不做解釋,以后有空詳細(xì)說(shuō),簡(jiǎn)單的說(shuō)就是原來(lái)的一個(gè)數(shù)據(jù)庫(kù)變成了多個(gè)數(shù)據(jù)庫(kù)。這時(shí)候,如果一個(gè)操作既訪問(wèn)01庫(kù),又訪問(wèn)02庫(kù),而且要保證數(shù)據(jù)的一致性,那么就要用到分布式事務(wù)。

2.2、應(yīng)用SOA化

所謂的SOA化,就是業(yè)務(wù)的服務(wù)化。比如原來(lái)單機(jī)支撐了整個(gè)電商網(wǎng)站,現(xiàn)在對(duì)整個(gè)網(wǎng)站進(jìn)行拆解,分離出了訂單中心、用戶中心、庫(kù)存中心。對(duì)于訂單中心,有專門(mén)的數(shù)據(jù)庫(kù)存儲(chǔ)訂單信息,用戶中心也有專門(mén)的數(shù)據(jù)庫(kù)存儲(chǔ)用戶信息,庫(kù)存中心也會(huì)有專門(mén)的數(shù)據(jù)庫(kù)存儲(chǔ)庫(kù)存信息。這時(shí)候如果要同時(shí)對(duì)訂單和庫(kù)存進(jìn)行操作,那么就會(huì)涉及到訂單數(shù)據(jù)庫(kù)和庫(kù)存數(shù)據(jù)庫(kù),為了保證數(shù)據(jù)一致性,就需要用到分布式事務(wù)。

以上兩種情況表象不同,但是本質(zhì)相同,都是因?yàn)橐僮鞯臄?shù)據(jù)庫(kù)變多了!

3、事務(wù)的ACID特性

3.1、原子性(A)

所謂的原子性就是說(shuō),在整個(gè)事務(wù)中的所有操作,要么全部完成,要么全部不做,沒(méi)有中間狀態(tài)。對(duì)于事務(wù)在執(zhí)行中發(fā)生錯(cuò)誤,所有的操作都會(huì)被回滾,整個(gè)事務(wù)就像從沒(méi)被執(zhí)行過(guò)一樣。

3.2、一致性(C)

事務(wù)的執(zhí)行必須保證系統(tǒng)的一致性,就拿轉(zhuǎn)賬為例,A有500元,B有300元,如果在一個(gè)事務(wù)里A成功轉(zhuǎn)給B50元,那么不管并發(fā)多少,不管發(fā)生什么,只要事務(wù)執(zhí)行成功了,那么最后A賬戶一定是450元,B賬戶一定是350元。

3.3、隔離性(I)

所謂的隔離性就是說(shuō),事務(wù)與事務(wù)之間不會(huì)互相影響,一個(gè)事務(wù)的中間狀態(tài)不會(huì)被其他事務(wù)感知。

3.4、持久性(D)

所謂的持久性,就是說(shuō)一單事務(wù)完成了,那么事務(wù)對(duì)數(shù)據(jù)所做的變更就完全保存在了數(shù)據(jù)庫(kù)中,即使發(fā)生停電,系統(tǒng)宕機(jī)也是如此。

4、分布式事務(wù)的應(yīng)用場(chǎng)景

4.1、支付

最經(jīng)典的場(chǎng)景就是支付了,一筆支付,是對(duì)買(mǎi)家賬戶進(jìn)行扣款,同時(shí)對(duì)賣家賬戶進(jìn)行加錢(qián),這些操作必須在一個(gè)事務(wù)里執(zhí)行,要么全部成功,要么全部失敗。而對(duì)于買(mǎi)家賬戶屬于買(mǎi)家中心,對(duì)應(yīng)的是買(mǎi)家數(shù)據(jù)庫(kù),而賣家賬戶屬于賣家中心,對(duì)應(yīng)的是賣家數(shù)據(jù)庫(kù),對(duì)不同數(shù)據(jù)庫(kù)的操作必然需要引入分布式事務(wù)。

4.2、在線下單

買(mǎi)家在電商平臺(tái)下單,往往會(huì)涉及到兩個(gè)動(dòng)作,一個(gè)是扣庫(kù)存,第二個(gè)是更新訂單狀態(tài),庫(kù)存和訂單一般屬于不同的數(shù)據(jù)庫(kù),需要使用分布式事務(wù)保證數(shù)據(jù)一致性。

5、常見(jiàn)的分布式事務(wù)解決方案

5.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)景變得非常狹隘。

5.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)。

5.3、TCC編程模式

所謂的TCC編程模式,也是兩階段提交的一個(gè)變種。TCC提供了一個(gè)編程框架,將整個(gè)業(yè)務(wù)邏輯分為三塊:Try、Confirm和Cancel三個(gè)操作。以在線下單為例,Try階段會(huì)去扣庫(kù)存,Confirm階段則是去更新訂單狀態(tài),如果更新訂單失敗,則進(jìn)入Cancel階段,會(huì)去恢復(fù)庫(kù)存??傊?,TCC就是通過(guò)代碼人為實(shí)現(xiàn)了兩階段提交,不同的業(yè)務(wù)場(chǎng)景所寫(xiě)的代碼都不一樣,復(fù)雜度也不一樣,因此,這種模式并不能很好地被復(fù)用。

6、總結(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ù)選型也是一種很重要的能力。

THEEND

最新評(píng)論(評(píng)論僅代表用戶觀點(diǎn))

更多
暫無(wú)評(píng)論