您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關(guān)分布式事務(wù)的解決方案有哪些,小編覺(jué)得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說(shuō),跟著小編一起來(lái)看看吧。
事務(wù),即將一個(gè)活動(dòng)涉及的所有操作作為一個(gè)不可分割的執(zhí)行單元,提供一種“要么一個(gè)都不執(zhí)行,要么全都執(zhí)行”的機(jī)制。在單機(jī)系統(tǒng)中,我們很容易能夠?qū)崿F(xiàn)一套滿足ACID特性的事務(wù)處理系統(tǒng),但是在分布式系統(tǒng)中,數(shù)據(jù)分散在各臺(tái)不同的機(jī)器上,如何對(duì)這些數(shù)據(jù)進(jìn)行分布式事務(wù)處理具有非常大的挑戰(zhàn)。
1、一個(gè)服務(wù)操作一個(gè)數(shù)據(jù)庫(kù)
一個(gè)服務(wù)一個(gè)數(shù)據(jù)庫(kù)
一個(gè)服務(wù)操作一個(gè)對(duì)應(yīng)的數(shù)據(jù)庫(kù),這就是我們大多數(shù)服務(wù)的場(chǎng)景,這種場(chǎng)景的事務(wù)很好保證,利用數(shù)據(jù)庫(kù)本身的事務(wù)特性即可,我們稱之為本地事務(wù)。
2、同一個(gè)服務(wù)操作多個(gè)數(shù)據(jù)庫(kù)
一個(gè)服務(wù)多個(gè)數(shù)據(jù)庫(kù)
隨著系統(tǒng)功能的增加,數(shù)據(jù)量的增多,我們可能需要隊(duì)數(shù)據(jù)庫(kù)進(jìn)行劃分,按照劃分方式,分為垂直劃分和水平劃分:
垂直劃分
隨著服務(wù)功能的增多,我們可能會(huì)把某些功能方法放到一個(gè)單獨(dú)的其他數(shù)據(jù)庫(kù)中,或者我們會(huì)直接去訪問(wèn)其他服務(wù)的數(shù)據(jù)庫(kù),這時(shí)就會(huì)操作多個(gè)數(shù)據(jù)庫(kù)了,我們把這種情況,稱為數(shù)據(jù)庫(kù)的垂直劃分。(其實(shí)這種場(chǎng)景不應(yīng)該存在,因?yàn)槿绻潜痉?wù)的,那么就應(yīng)該是同一個(gè)數(shù)據(jù)庫(kù)為好;如果是其他的服務(wù),那么不應(yīng)該直接操作其他服務(wù)的數(shù)據(jù)庫(kù),而是應(yīng)該調(diào)用其他服務(wù)提供的接口),因此這種場(chǎng)景不是很常見(jiàn);
水平劃分
上面那種場(chǎng)景不常見(jiàn),但還有一種情況,卻是經(jīng)常遇到的,尤其是數(shù)據(jù)量很大的情況下。那就是當(dāng)我們對(duì)數(shù)據(jù)庫(kù)進(jìn)行分庫(kù)分表后,這時(shí)候就需要操作多個(gè)數(shù)據(jù)庫(kù)了,這種情況我們稱為水平劃分;
3、微服務(wù)SOA跨服務(wù)調(diào)用
微服務(wù)調(diào)用
上面說(shuō)到直接操作其他服務(wù)的DB,并不合適,正確的方式是使用其他服務(wù)提供的接口。
“一個(gè)服務(wù)操作一個(gè)數(shù)據(jù)庫(kù)”的場(chǎng)景的事務(wù),我們稱之為本地事務(wù);“同一個(gè)服務(wù)操作多個(gè)數(shù)據(jù)庫(kù)”和“微服務(wù)SOA跨服務(wù)調(diào)用”這兩種的事務(wù),我們稱之為分布式事務(wù)。
對(duì)于本地事務(wù),我們可以利用數(shù)據(jù)庫(kù)本身的事務(wù)特性保證事務(wù),那么在分布式場(chǎng)景下,我們?cè)撊绾伪WC事務(wù)了?
談到事務(wù),就必須知道三個(gè)規(guī)則,分別是:ACID,CAP和BASE。單機(jī)系統(tǒng)一般遵循ACID規(guī)則;而分布式系統(tǒng)則一般遵循CAP規(guī)則或者BASE規(guī)則。
ACID是事務(wù)的四個(gè)基本性質(zhì),屬于傳統(tǒng)數(shù)據(jù)庫(kù)常用的設(shè)計(jì)理念,追求強(qiáng)一致性模型。ACID是指Atomicity(原子性)、Consistency(一致性)、Isolation(隔離型)、Durability(持久性):
A:原子性(Atomicity)
一個(gè)事務(wù)(transaction)中的所有操作,要么全部完成,要么全部不完成,不會(huì)結(jié)束在中間某個(gè)環(huán)節(jié)。事務(wù)在執(zhí)行過(guò)程中發(fā)生錯(cuò)誤,會(huì)被回滾(Rollback)到事務(wù)開(kāi)始前的狀態(tài),就像這個(gè)事務(wù)從來(lái)沒(méi)有執(zhí)行過(guò)一樣。
C:一致性(Consistency)
事務(wù)的一致性指的是在一個(gè)事務(wù)執(zhí)行之前和執(zhí)行之后數(shù)據(jù)庫(kù)都必須處于一致性狀態(tài)。如果事務(wù)成功地完成,那么系統(tǒng)中所有變化將正確地應(yīng)用,系統(tǒng)處于有效狀態(tài)。如果在事務(wù)中出現(xiàn)錯(cuò)誤,那么系統(tǒng)中的所有變化將自動(dòng)地回滾,系統(tǒng)返回到原始狀態(tài)。
I:隔離型(Isolation)
指的是在并發(fā)環(huán)境中,當(dāng)不同的事務(wù)同時(shí)操縱相同的數(shù)據(jù)時(shí),每個(gè)事務(wù)都有各自的完整數(shù)據(jù)空間。由并發(fā)事務(wù)所做的修改必須與任何其他并發(fā)事務(wù)所做的修改隔離。事務(wù)查看數(shù)據(jù)更新時(shí),數(shù)據(jù)所處的狀態(tài)要么是另一事務(wù)修改它之前的狀態(tài),要么是另一事務(wù)修改它之后的狀態(tài),事務(wù)不會(huì)查看到中間狀態(tài)的數(shù)據(jù)。
D:持久性(Durability)
指的是只要事務(wù)成功結(jié)束,它對(duì)數(shù)據(jù)庫(kù)所做的更新就必須永久保存下來(lái)。即使發(fā)生系統(tǒng)崩潰,重新啟動(dòng)數(shù)據(jù)庫(kù)系統(tǒng)后,數(shù)據(jù)庫(kù)還能恢復(fù)到事務(wù)成功結(jié)束時(shí)的狀態(tài)。
CAP
CAP是Consistent(一致性)、Available(可用性)和Partition Tolerance (分區(qū)容錯(cuò)性)三個(gè)詞的縮寫:
C (一致性):對(duì)某個(gè)指定的客戶端來(lái)說(shuō),讀操作能返回最新的寫操作。對(duì)于數(shù)據(jù)分布在不同節(jié)點(diǎn)上的數(shù)據(jù)上來(lái)說(shuō),如果在某個(gè)節(jié)點(diǎn)更新了數(shù)據(jù),那么在其他節(jié)點(diǎn)如果都能讀取到這個(gè)最新的數(shù)據(jù),那么就稱為強(qiáng)一致,如果有某個(gè)節(jié)點(diǎn)沒(méi)有讀取到,那就是分布式不一致。
A (可用性):非故障的節(jié)點(diǎn)在合理的時(shí)間內(nèi)返回合理的響應(yīng)(不是錯(cuò)誤和超時(shí)的響應(yīng))。可用性的兩個(gè)關(guān)鍵一個(gè)是合理的時(shí)間,一個(gè)是合理的響應(yīng)。合理的時(shí)間指的是請(qǐng)求不能無(wú)限被阻塞,應(yīng)該在合理的時(shí)間給出返回。合理的響應(yīng)指的是系統(tǒng)應(yīng)該明確返回結(jié)果并且結(jié)果是正確的,這里的正確指的是比如應(yīng)該返回50,而不是返回40。
P (分區(qū)容錯(cuò)性):當(dāng)出現(xiàn)網(wǎng)絡(luò)分區(qū)后,系統(tǒng)能夠繼續(xù)工作。打個(gè)比方,這里個(gè)集群有多臺(tái)機(jī)器,有臺(tái)機(jī)器網(wǎng)絡(luò)出現(xiàn)了問(wèn)題,但是這個(gè)集群仍然可以正常工作。
CAP三者不可能共有,一個(gè)分布式系統(tǒng)最多只能同時(shí)滿足一致性(Consistence)、可用性(Availability)和分區(qū)容錯(cuò)性(Partition tolerance)這三項(xiàng)中的兩項(xiàng):
CA without P
這種情況在分布式系統(tǒng)中幾乎是不存在的。在分布式環(huán)境下,主機(jī)眾多、部署分散,分區(qū)是一個(gè)必然的事實(shí)。在這個(gè)存在分區(qū)的事實(shí)下,我們選擇了CA而放棄了P,那么為了保證一致性,這個(gè)時(shí)候必須拒絕請(qǐng)求,但是A又不允許。因此在分布式場(chǎng)景下,不可能選擇CA架構(gòu),只能選擇CP或者AP架構(gòu)。
我們熟知的關(guān)系型數(shù)據(jù)庫(kù)是CA架構(gòu),如My Sql和Oracle就是保證了可用性和數(shù)據(jù)一致性,但是他并不是個(gè)分布式系統(tǒng)。一旦關(guān)系型數(shù)據(jù)庫(kù)要考慮主備同步、集群部署等就必須要把P也考慮進(jìn)來(lái)。
CP without A
如果一個(gè)分布式系統(tǒng)不要求強(qiáng)的可用性,即容許系統(tǒng)停機(jī)或者長(zhǎng)時(shí)間無(wú)響應(yīng)的話,就可以在CAP三者中保障CP而舍棄A。一個(gè)保證了CP而一個(gè)舍棄了A的分布式系統(tǒng),一旦發(fā)生網(wǎng)絡(luò)故障或者消息丟失等情況,就要犧牲用戶的體驗(yàn),等待所有數(shù)據(jù)全部一致了之后再讓用戶訪問(wèn)系統(tǒng)。
設(shè)計(jì)成CP的系統(tǒng)的,最典型的就是很多分布式數(shù)據(jù)庫(kù),他們都是設(shè)計(jì)成CP的。在發(fā)生極端情況時(shí),優(yōu)先保證數(shù)據(jù)的強(qiáng)一致性,代價(jià)就是舍棄系統(tǒng)的可用性。如Redis、HBase等,還有分布式系統(tǒng)中常用的Zookeeper也是在CAP三者之中選擇優(yōu)先保證CP的。對(duì)于大規(guī)模金融服務(wù)也是,他們必須保證C,同時(shí)存在P,因此也只能犧牲A.
AP wihtout C
要高可用并允許分區(qū),則需放棄一致性。一旦網(wǎng)絡(luò)問(wèn)題發(fā)生,節(jié)點(diǎn)之間可能會(huì)失去聯(lián)系。為了保證高可用,需要在用戶訪問(wèn)時(shí)可以馬上得到返回,則每個(gè)節(jié)點(diǎn)只能用本地?cái)?shù)據(jù)提供服務(wù),而這樣會(huì)導(dǎo)致全局?jǐn)?shù)據(jù)的不一致性。
這種舍棄強(qiáng)一致性而保證系統(tǒng)的分區(qū)容錯(cuò)性和可用性的場(chǎng)景和案例非常多。前面我們介紹可用性的時(shí)候說(shuō)到過(guò),很多系統(tǒng)在可用性方面會(huì)做很多事情來(lái)保證系統(tǒng)的全年可用性可以達(dá)到N個(gè)9,所以,對(duì)于很多業(yè)務(wù)系統(tǒng)來(lái)說(shuō),比如淘寶的購(gòu)物,12306的買票。都是在可用性和一致性之間舍棄了一致性而選擇可用性。
你在12306買票的時(shí)候肯定遇到過(guò)這種場(chǎng)景,當(dāng)你購(gòu)買的時(shí)候提示你是有票的(但是可能實(shí)際已經(jīng)沒(méi)票了),你也正常的去輸入驗(yàn)證碼,下單了。但是過(guò)了一會(huì)系統(tǒng)提示你下單失敗,余票不足。這其實(shí)就是先在可用性方面保證系統(tǒng)可以正常的服務(wù),然后在數(shù)據(jù)的一致性方面做了些犧牲,會(huì)影響一些用戶體驗(yàn),但是也不至于造成用戶流程的嚴(yán)重阻塞。
但是,我們說(shuō)很多網(wǎng)站犧牲了一致性,選擇了可用性,這其實(shí)也不準(zhǔn)確的。就比如上面的買票的例子,其實(shí)舍棄的只是強(qiáng)一致性。退而求其次保證了最終一致性。也就是說(shuō),雖然下單的瞬間,關(guān)于車票的庫(kù)存可能存在數(shù)據(jù)不一致的情況,但是過(guò)了一段時(shí)間,還是要保證最終一致性的。
對(duì)于多數(shù)大型互聯(lián)網(wǎng)應(yīng)用的場(chǎng)景,主機(jī)眾多、部署分散,而且現(xiàn)在的集群規(guī)模越來(lái)越大,所以節(jié)點(diǎn)故障、網(wǎng)絡(luò)故障是常態(tài),而且要保證服務(wù)可用性達(dá)到N個(gè)9,即保證P和A,舍棄C(退而求其次保證最終一致性)。雖然某些地方會(huì)影響客戶體驗(yàn),但沒(méi)達(dá)到造成用戶流程的嚴(yán)重程度。
對(duì)于AP來(lái)說(shuō),放棄一致性(這里說(shuō)的一致性是強(qiáng)一致性),追求分區(qū)容錯(cuò)性和可用性,這是很多分布式系統(tǒng)設(shè)計(jì)時(shí)的選擇,后面的BASE也是根據(jù)AP來(lái)擴(kuò)展。
BASE理論是對(duì)CAP理論的延伸,核心思想是即使無(wú)法做到強(qiáng)一致性(CAP的一致性就是強(qiáng)一致性),但應(yīng)用可以采用適合的方式達(dá)到最終一致性。
BASE 是指 Basically Available(基本可用)、Soft state(軟狀態(tài))和 Eventually consistent (最終一致性):
基本可用:分布式系統(tǒng)在出現(xiàn)故障時(shí),允許損失部分可用功能,保證核心功能可用。
軟狀態(tài):允許系統(tǒng)中存在中間狀態(tài),這個(gè)狀態(tài)不影響系統(tǒng)可用性,這里指的是CAP中的不一致。
最終一致:最終一致是指經(jīng)過(guò)一段時(shí)間后,所有節(jié)點(diǎn)數(shù)據(jù)都將會(huì)達(dá)到一致。
BASE中用軟狀態(tài)和最終一致,保證了分布死網(wǎng)絡(luò)延遲后的一致性。BASE和 ACID 是相反的,它完全不同于ACID的強(qiáng)一致性模型,而是通過(guò)犧牲強(qiáng)一致性來(lái)獲得可用性,并允許數(shù)據(jù)在一段時(shí)間內(nèi)是不一致的,但最終達(dá)到一致?tīng)顟B(tài)。
目前分布式事務(wù)解決的方案主要有對(duì)業(yè)務(wù)無(wú)入侵和有入侵的方案,無(wú)入侵方案主要有基于數(shù)據(jù)庫(kù) XA 協(xié)議的兩段式提交(2PC)方案,它的優(yōu)點(diǎn)是對(duì)業(yè)務(wù)代碼無(wú)入侵,但是它的缺點(diǎn)也是很明顯:必須要求數(shù)據(jù)庫(kù)對(duì) XA 協(xié)議的支持,且由于 XA 協(xié)議自身的特點(diǎn),它會(huì)造成事務(wù)資源長(zhǎng)時(shí)間得不到釋放,鎖定周期長(zhǎng),而且在應(yīng)用層上面無(wú)法干預(yù),因此它性能很差,它的存在相當(dāng)于七傷拳那樣“傷人七分,損己三分”,因此在互聯(lián)網(wǎng)項(xiàng)目中并不是很流行這種解決方案。
為了這個(gè)彌補(bǔ)這種方案帶來(lái)性能低的問(wèn)題,又想出了很多種方案來(lái)解決,但這無(wú)一例外都需要通過(guò)在應(yīng)用層做手腳,即入侵業(yè)務(wù)的方式,比如很出名的 TCC 方案,基于 TCC 也有很多成熟的框架,如 ByteTCC、tcc-transaction 等。以及基于可靠消息的最終一致性來(lái)實(shí)現(xiàn),如 RocketMQ 的事務(wù)消息。
入侵代碼的方案是基于現(xiàn)有情形“迫不得已”才推出的解決方案,實(shí)際上它們實(shí)現(xiàn)起來(lái)非常不優(yōu)雅,一個(gè)事務(wù)的調(diào)用通常伴隨而來(lái)的是對(duì)該事務(wù)接口增加一系列的反向操作,比如 TCC 三段式提交,提交邏輯必然伴隨著回滾的邏輯,這樣的代碼會(huì)使得項(xiàng)目非常臃腫,維護(hù)成本高。
在分布式系統(tǒng)中,每個(gè)節(jié)點(diǎn)雖然可以知曉自己的操作時(shí)成功或者失敗,卻無(wú)法知道其他節(jié)點(diǎn)的操作的成功或失敗。當(dāng)一個(gè)事務(wù)跨越多個(gè)節(jié)點(diǎn)時(shí),需要引入一個(gè)作為協(xié)調(diào)者的組件來(lái)統(tǒng)一掌控所有節(jié)點(diǎn)(稱作參與者)的操作結(jié)果并最終指示這些節(jié)點(diǎn)是否要把操作結(jié)果進(jìn)行真正的提交(比如將更新后的數(shù)據(jù)寫入磁盤等)。因此,二階段提交的思路可以概括為:參與者將操作成敗通知協(xié)調(diào)者,再由協(xié)調(diào)者根據(jù)所有參與者的反饋情報(bào)決定各參與者是否要提交操作還是中止操作。所謂的兩個(gè)階段是指:第一階段:準(zhǔn)備階段;第二階段:提交階段。
事務(wù)協(xié)調(diào)者(事務(wù)管理器)給每個(gè)參與者(資源管理器)發(fā)送Prepare消息,每個(gè)參與者要么直接返回失敗(如權(quán)限驗(yàn)證失敗),要么在本地執(zhí)行事務(wù),寫本地的redo和undo日志,但不提交,到達(dá)一種“萬(wàn)事俱備,只欠東風(fēng)”的狀態(tài)。
詳細(xì)步驟如下:
1)協(xié)調(diào)者節(jié)點(diǎn)向所有參與者節(jié)點(diǎn)詢問(wèn)是否可以執(zhí)行提交操作(vote),并開(kāi)始等待各參與者節(jié)點(diǎn)的響應(yīng);
2)參與者節(jié)點(diǎn)執(zhí)行詢問(wèn)發(fā)起為止的所有事務(wù)操作,并將Undo信息和Redo信息寫入日志;
3)各參與者節(jié)點(diǎn)響應(yīng)協(xié)調(diào)者節(jié)點(diǎn)發(fā)起的詢問(wèn)。如果參與者節(jié)點(diǎn)的事務(wù)操作實(shí)際執(zhí)行成功,則它返回一個(gè)”同意”消息;如果參與者節(jié)點(diǎn)的事務(wù)操作實(shí)際執(zhí)行失敗,則它返回一個(gè)”中止”消息。
如果協(xié)調(diào)者收到了參與者的失敗消息或者超時(shí),直接給每個(gè)參與者發(fā)送回滾(Rollback)消息;否則,發(fā)送提交(Commit)消息;參與者根據(jù)協(xié)調(diào)者的指令執(zhí)行提交或者回滾操作,釋放所有事務(wù)處理過(guò)程中使用的鎖資源。
提交通過(guò)
所有的參與者,如果在準(zhǔn)備階段,都返回OK,那么第二階段均進(jìn)行提交。
提交通過(guò)
提交回滾
所有參與者,在準(zhǔn)備階段,只要有一個(gè)返回NO,那么第二階段就都進(jìn)行回滾。
提交回滾
單點(diǎn)問(wèn)題:事務(wù)管理器在整個(gè)流程中扮演的角色很關(guān)鍵,如果其宕機(jī),比如在第一階段已經(jīng)完成,在第二階段正準(zhǔn)備提交的時(shí)候事務(wù)管理器宕機(jī),資源管理器就會(huì)一直阻塞,導(dǎo)致數(shù)據(jù)庫(kù)無(wú)法使用。
同步阻塞:在準(zhǔn)備就緒之后,資源管理器中的資源一直處于阻塞,直到提交完成,釋放資源。
數(shù)據(jù)不一致:兩階段提交協(xié)議雖然為分布式數(shù)據(jù)強(qiáng)一致性所設(shè)計(jì),但仍然存在數(shù)據(jù)不一致性的可能,比如在第二階段中,假設(shè)協(xié)調(diào)者發(fā)出了事務(wù)commit的通知,但是因?yàn)榫W(wǎng)絡(luò)問(wèn)題該通知僅被一部分參與者所收到并執(zhí)行了commit操作,其余的參與者則因?yàn)闆](méi)有收到通知一直處于阻塞狀態(tài),這時(shí)候就產(chǎn)生了數(shù)據(jù)的不一致性。
總的來(lái)說(shuō),XA協(xié)議比較簡(jiǎn)單,成本較低,但是其單點(diǎn)問(wèn)題,以及不能支持高并發(fā)(由于同步阻塞)依然是其最大的弱點(diǎn)。
TCC與2PC二階段提交機(jī)制類似,區(qū)別在于層面不同,2PC是在數(shù)據(jù)庫(kù)層面解決數(shù)據(jù)庫(kù)之間的分布式事務(wù),TCC是在應(yīng)用層面解決分布式系統(tǒng)中的分布式事務(wù)。
TCC模式需要事務(wù)參與者根據(jù)自己的業(yè)務(wù)場(chǎng)景實(shí)現(xiàn) Try、Confirm 和 Cancel 三個(gè)操作接口;事務(wù)參與者在一階段中,執(zhí)行Try方式;在二階段中,如果是提交,則執(zhí)行Confirm方法,如果是回滾,則執(zhí)行 Cancel方法:
Try接口:嘗試執(zhí)行,完成所有業(yè)務(wù)檢查(一致性),預(yù)留必須業(yè)務(wù)資源(準(zhǔn)隔離性)
Confirm接口:確認(rèn)執(zhí)行真正執(zhí)行業(yè)務(wù),不作任何業(yè)務(wù)檢查,只使用Try階段預(yù)留的業(yè)務(wù)資源,Confirm要求一定要成功,因此Confirm失敗后需要進(jìn)行重試。因此Confirm操作需要滿足冪等性。
Cancel接口:釋放Try階段預(yù)留的業(yè)務(wù)資源。Cancel操作失敗也會(huì)一直重試,因此也需要滿足冪等性。
舉個(gè)簡(jiǎn)單的例子,你去商店用兩30塊錢買一瓶礦泉水,那么參與方為你和店主,資源為你的錢和老板的水,操作為你付錢,老板收錢和給你水:
第一階段(try):各自檢查并資源。對(duì)于你,你需要檢查你錢包里是否夠2塊錢,如果有那么就要凍結(jié)這兩塊錢;對(duì)于老板,它看看冰箱里是不是還要礦泉水,如果有,那么鎖定這瓶水。
第二階段(Confirm):如果你和老板都檢查了,沒(méi)問(wèn)題,那么就執(zhí)行交易Confirm,你付兩塊錢,老板收到兩塊錢,并給你一瓶礦礦水。
第二階段(Cancel):如果你倆在檢查時(shí),操作有失敗情況或者超時(shí),則進(jìn)行cancel,你解凍你的錢,老板的那一瓶水也可以賣給別人了;
對(duì)于你這邊,詳細(xì)列出TCC執(zhí)行過(guò)程,如下:
TCC過(guò)程示例
用戶接入 TCC 模式,最重要的事情就是考慮如何將業(yè)務(wù)模型拆成 2 階段,實(shí)現(xiàn)成 TCC 的 3 個(gè)方法,并且保證 Try 成功 Confirm 一定能成功。相對(duì)于 AT 模式,TCC 模式對(duì)業(yè)務(wù)代碼有一定的侵入性,但是 TCC 模式無(wú) AT 模式的全局行鎖,TCC 性能會(huì)比 AT 模式高很多。
此方案的核心是將需要分布式處理的任務(wù)通過(guò)消息日志的方式來(lái)異步執(zhí)行。消息日志可以存儲(chǔ)到本地文本、數(shù)據(jù)庫(kù)或消息隊(duì)列,再通過(guò)業(yè)務(wù)規(guī)則自動(dòng)或人工發(fā)起重試。人工重試更多的是應(yīng)用于支付場(chǎng)景,通過(guò)對(duì)賬系統(tǒng)對(duì)事后問(wèn)題的處理。
本地消息表
對(duì)于本地消息隊(duì)列來(lái)說(shuō)核心是把大事務(wù)轉(zhuǎn)變?yōu)樾∈聞?wù)。還是舉上面用100元去買一瓶水的例子。
1)當(dāng)你扣錢的時(shí)候,你需要在你扣錢的服務(wù)器上新增加一個(gè)本地消息表,你需要把你扣錢和寫入減去水的庫(kù)存到本地消息表放入同一個(gè)事務(wù)(依靠數(shù)據(jù)庫(kù)本地事務(wù)保證一致性);
2.這個(gè)時(shí)候有個(gè)定時(shí)任務(wù)去輪詢這個(gè)本地事務(wù)表,把沒(méi)有發(fā)送的消息,扔給商品庫(kù)存服務(wù)器,叫他減去水的庫(kù)存,到達(dá)商品服務(wù)器之后這個(gè)時(shí)候得先寫入這個(gè)服務(wù)器的事務(wù)表,然后進(jìn)行扣減,扣減成功后,更新事務(wù)表中的狀態(tài);
3.商品服務(wù)器通過(guò)定時(shí)任務(wù)掃描消息表或者直接通知扣錢服務(wù)器,扣錢服務(wù)器本地消息表進(jìn)行狀態(tài)更新;
4.針對(duì)一些異常情況,定時(shí)掃描未成功處理的消息,進(jìn)行重新發(fā)送,在商品服務(wù)器接到消息之后,首先判斷是否是重復(fù)的,如果已經(jīng)接收,在判斷是否執(zhí)行,如果執(zhí)行在馬上又進(jìn)行通知事務(wù),如果未執(zhí)行,需要重新執(zhí)行需要由業(yè)務(wù)保證冪等,也就是不會(huì)多扣一瓶水;
本地消息隊(duì)列是BASE理論,是最終一致模型,適用于對(duì)一致性要求不高的。實(shí)現(xiàn)這個(gè)模型時(shí)需要注意重試的冪等。
在RocketMQ中實(shí)現(xiàn)了分布式事務(wù),實(shí)際上其實(shí)是對(duì)本地消息表的一個(gè)封裝,將本地消息表移動(dòng)到了MQ內(nèi)部,下面簡(jiǎn)單介紹一下MQ事務(wù)
基本流程如下:
第一階段Prepared消息,會(huì)拿到消息的地址。
第二階段執(zhí)行本地事務(wù)。
第三階段通過(guò)第一階段拿到的地址去訪問(wèn)消息,并修改狀態(tài)。消息接受者就能使用這個(gè)消息。
如果確認(rèn)消息失敗,在RocketMq Broker中提供了定時(shí)掃描沒(méi)有更新?tīng)顟B(tài)的消息,如果有消息沒(méi)有得到確認(rèn),會(huì)向消息發(fā)送者發(fā)送消息,來(lái)判斷是否提交,在rocketmq中是以listener的形式給發(fā)送者,用來(lái)處理。
如果消費(fèi)超時(shí),則需要一直重試,消息接收端需要保證冪等。如果消息消費(fèi)失敗,這個(gè)就需要人工進(jìn)行處理,因?yàn)檫@個(gè)概率較低,如果為了這種小概率時(shí)間而設(shè)計(jì)這個(gè)復(fù)雜的流程反而得不償失
Saga是30年前一篇數(shù)據(jù)庫(kù)倫理提到的一個(gè)概念。其核心思想是將長(zhǎng)事務(wù)拆分為多個(gè)本地短事務(wù),由Saga事務(wù)協(xié)調(diào)器協(xié)調(diào),如果正常結(jié)束那就正常完成,如果某個(gè)步驟失敗,則根據(jù)相反順序一次調(diào)用補(bǔ)償操作。
每個(gè)Saga由一系列sub-transaction Ti 組成 每個(gè)Ti 都有對(duì)應(yīng)的補(bǔ)償動(dòng)作Ci,補(bǔ)償動(dòng)作用于撤銷Ti造成的結(jié)果,這里的每個(gè)T,都是一個(gè)本地事務(wù)??梢钥吹剑蚑CC相比,Saga沒(méi)有“預(yù)留 try”動(dòng)作,它的Ti就是直接提交到庫(kù)。
Saga的執(zhí)行順序有兩種:
T1, T2, T3, ..., Tn
T1, T2, ..., Tj, Cj,..., C2, C1,其中0 < j < n Saga定義了兩種恢復(fù)策略:
向后恢復(fù),即上面提到的第二種執(zhí)行順序,其中j是發(fā)生錯(cuò)誤的sub-transaction,這種做法的效果是撤銷掉之前所有成功的sub-transation,使得整個(gè)Saga的執(zhí)行結(jié)果撤銷。
向前恢復(fù),適用于必須要成功的場(chǎng)景,執(zhí)行順序是類似于這樣的:T1, T2, ..., Tj(失敗), Tj(重試),..., Tn,其中j是發(fā)生錯(cuò)誤的sub-transaction。該情況下不需要Ci。
這里要注意的是,在saga模式中不能保證隔離性,因?yàn)闆](méi)有鎖住資源,其他事務(wù)依然可以覆蓋或者影響當(dāng)前事務(wù)。
還是拿100元買一瓶水的例子來(lái)說(shuō),這里定義
T1=扣100元 T2=給用戶加一瓶水 T3=減庫(kù)存一瓶水
C1=加100元 C2=給用戶減一瓶水 C3=給庫(kù)存加一瓶水
我們一次進(jìn)行T1,T2,T3如果發(fā)生問(wèn)題,就執(zhí)行發(fā)生問(wèn)題的C操作的反向。
上面說(shuō)到的隔離性的問(wèn)題會(huì)出現(xiàn)在,如果執(zhí)行到T3這個(gè)時(shí)候需要執(zhí)行回滾,但是這個(gè)用戶已經(jīng)把水喝了(另外一個(gè)事務(wù)),回滾的時(shí)候就會(huì)發(fā)現(xiàn),無(wú)法給用戶減一瓶水了。這就是事務(wù)之間沒(méi)有隔離性的問(wèn)題
可以看見(jiàn)saga模式?jīng)]有隔離性的影響還是較大,可以參照華為的解決方案:從業(yè)務(wù)層面入手加入一 Session 以及鎖的機(jī)制來(lái)保證能夠串行化操作資源。也可以在業(yè)務(wù)層面通過(guò)預(yù)先凍結(jié)資金的方式隔離這部分資源, 最后在業(yè)務(wù)操作的過(guò)程中可以通過(guò)及時(shí)讀取當(dāng)前狀態(tài)的方式獲取到最新的更新。
以上就是分布式事務(wù)的解決方案有哪些,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見(jiàn)到或用到的。希望你能通過(guò)這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。