溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何理解Java分布式事務(wù)

發(fā)布時(shí)間:2022-01-17 09:42:28 來(lái)源:億速云 閱讀:143 作者:iii 欄目:數(shù)據(jù)庫(kù)

今天小編給大家分享一下如何理解Java分布式事務(wù)的相關(guān)知識(shí)點(diǎn),內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識(shí),所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來(lái)了解一下吧。

如果一個(gè)事務(wù)調(diào)用了不同服務(wù)器上的操作,那么它就成為了一個(gè)分布式事務(wù)。

考慮下面一種場(chǎng)景:當(dāng)你發(fā)了工資之后,把你的當(dāng)月工資¥1024從支付寶轉(zhuǎn)到了余額寶。

如果在支付寶賬戶扣除¥1024之后,余額寶系統(tǒng)掛掉了,余額寶的賬戶并沒(méi)有增加¥1024,這時(shí)候就出現(xiàn)了數(shù)據(jù)不一致的情況。

在很多系統(tǒng)中都能找到上述情況的影子:

  • 在下單的時(shí)候,需要在訂單表中插入一條數(shù)據(jù),然后把庫(kù)存減去一

  • 在搜索的時(shí)候如果點(diǎn)擊了廣告,需要先記錄該點(diǎn)擊事件,然后通知商家系統(tǒng)扣除廣告費(fèi)

在一個(gè)分布式事務(wù)結(jié)束的時(shí)候,事務(wù)的原子特性要求所有參與該事務(wù)的服務(wù)器必須全部提交或全部放棄該事務(wù)。為了實(shí)現(xiàn)這一點(diǎn),其中一個(gè)服務(wù)器承擔(dān)了協(xié)調(diào)者(coordinater)的角色,由它來(lái)保證所有的服務(wù)器獲得相同的結(jié)果。

協(xié)調(diào)者(coordinater)的工作方式取決于它選用的協(xié)議,“兩階段提交”是分布式事務(wù)最常用的協(xié)議。

1、two-phase commit protocol

兩階段提交協(xié)議(two-phase commit protocol)的設(shè)計(jì)出發(fā)點(diǎn)是允許任何一個(gè)參與者自行放棄它自己的那部分事務(wù)。由于事務(wù)原子性的要求,如果部分事務(wù)被放棄,那么整個(gè)分布式事務(wù)也必須被放棄。

在該協(xié)議的第一個(gè)階段,每個(gè)參與者投票表決該事務(wù)是放棄還是提交,一旦參與者要求提交事務(wù),那么就不允許放棄該事務(wù)。因此,在一個(gè)參與者要求提交事務(wù)之前,它必須保證最終能夠執(zhí)行分布式事務(wù)中自己的那部分,即使該參與者出現(xiàn)故障而被中途替換掉。

一個(gè)事務(wù)的參與者如果最終能提交事務(wù),那么可以說(shuō)參與者處于事務(wù)的準(zhǔn)備好(prepared)狀態(tài)。為了保證能夠提交,每個(gè)參與者必須將事務(wù)中所有發(fā)生改變的對(duì)象以及自身的狀態(tài)(prepared)保存到持久性存儲(chǔ)中。

在該協(xié)議的第二個(gè)階段,事務(wù)的每個(gè)參與者執(zhí)行最終統(tǒng)一的決定。如果任何一個(gè)參與者投票放棄事務(wù),那么最終的決定是放棄事務(wù)。如果所有的參與者都投票提交事務(wù),那么最終的決定是提交事務(wù)。

問(wèn)題在于,要保證每個(gè)參與者都投票,并且達(dá)成一個(gè)共同的決定。在無(wú)故障時(shí),該協(xié)議相當(dāng)簡(jiǎn)單。但是,協(xié)議必須在出現(xiàn)各種故障(例如服務(wù)器崩潰,消息丟失或服務(wù)暫時(shí)無(wú)法通信)時(shí)能夠正常工作。

2、兩階段提交的實(shí)現(xiàn)

為了實(shí)現(xiàn)兩階段提交協(xié)議,分布式事務(wù)中的協(xié)調(diào)者和參與者通常按照下面的接口進(jìn)行通信:

  • canCommit(trans) ?

協(xié)調(diào)者詢問(wèn)參與者是否可以提交事務(wù),參與者回復(fù)自己的投票結(jié)果。

  • doCommit(trans) 

協(xié)調(diào)者告訴參與者提交它的那部分事務(wù)。

  • doAbort(trans) 

協(xié)調(diào)者告訴參與者放棄它的那部分事務(wù)。

  • haveCommitted(trans, participant) 

參與者用該操作向協(xié)調(diào)者確認(rèn)它提交了事務(wù)。

  • getDecision(trans) ?

當(dāng)參與者在投Yes票后一段時(shí)間內(nèi)未收到應(yīng)答時(shí),參與者用該操作向協(xié)調(diào)者詢問(wèn)事務(wù)的投票表決結(jié)果。該操作用于從服務(wù)器崩潰或從消息延遲中恢復(fù)。

階段一(投票階段): 1)協(xié)調(diào)者向分布式事務(wù)的所有參與者發(fā)送canCommit?請(qǐng)求 2)當(dāng)參與者收到canCommit請(qǐng)求后,它向協(xié)調(diào)者回復(fù)自己的投票(Yes/No)。    在投Yes票之前,它在持久性存儲(chǔ)中保存所有對(duì)象,準(zhǔn)備提交。如果投No票,參與者立即放棄。 階段二(提交階段): 1)協(xié)調(diào)者收集所有的投票(包括它自己的投票)。    a)如果不存在故障并且所有的投票都是Yes時(shí),那么協(xié)調(diào)者將決定提交事務(wù)并向所有參與者發(fā)送doCommit       請(qǐng)求    b)否則,協(xié)調(diào)者決定放棄該事務(wù),并向所有投Yes票的參與者發(fā)送doAbort請(qǐng)求 2)投Yes票的等待者等待協(xié)調(diào)者發(fā)送的doCommit或者doAbort請(qǐng)求。一旦參與者接收到任何一種請(qǐng)求消息,    它將根據(jù)該請(qǐng)求放棄或者提交事務(wù)。如果請(qǐng)求是提交事務(wù),那么他還要向協(xié)調(diào)者發(fā)送一個(gè)haveCommitted    來(lái)確認(rèn)事務(wù)已經(jīng)提交

3、分布式事務(wù)的故障模型

在分布式事務(wù)中執(zhí)行的過(guò)程中,可能出現(xiàn)磁盤(pán)故障,進(jìn)程崩潰以及消息的丟失,超時(shí)等。

兩階段提交是一種達(dá)成共識(shí)的協(xié)議,在該系統(tǒng)中,如果進(jìn)程崩潰,那么是不可能達(dá)成共識(shí)的。但是,兩階段提交卻是在這些條件下達(dá)成了共識(shí),這是由于進(jìn)程的崩潰被屏蔽,崩潰的進(jìn)程被一個(gè)新的進(jìn)程取代,新進(jìn)程的狀態(tài)根據(jù)持久性存儲(chǔ)中保存的信息和其他進(jìn)程擁有的信息來(lái)設(shè)定。

3.1、故障模型

Lampson提出過(guò)一個(gè)分布式事務(wù)的故障模型,包括了硬盤(pán)故障、服務(wù)器故障以及通信故障。該故障模型聲稱:可以保證算法在出現(xiàn)故障時(shí)正確工作,但是對(duì)于不可預(yù)見(jiàn)的災(zāi)難性故障則不能正確處理。盡管會(huì)出現(xiàn)錯(cuò)誤,但是可以在發(fā)生不正確行為之前發(fā)現(xiàn)并處理這些錯(cuò)誤。Lampson的故障模型包括以下故障:

  • 對(duì)持久性存儲(chǔ)的寫(xiě)操作可能發(fā)生故障(或因?yàn)閷?xiě)操作無(wú)效或因?yàn)閷?xiě)入錯(cuò)誤的值)。例如,將數(shù)據(jù)寫(xiě)到錯(cuò)誤的磁盤(pán)塊被認(rèn)為是災(zāi)難性故障。文件存儲(chǔ)可能損壞。在持久性存儲(chǔ)中讀數(shù)據(jù)時(shí)可根據(jù)校驗(yàn)和來(lái)判斷數(shù)據(jù)塊是否損壞。

  • 服務(wù)器可能偶爾崩潰。當(dāng)一個(gè)崩潰的服務(wù)器由一個(gè)新進(jìn)程取代后,它的可變內(nèi)存被重置,崩潰之前的數(shù)據(jù)均丟失。此后新進(jìn)程執(zhí)行一個(gè)可恢復(fù)過(guò)程,根據(jù)持久存儲(chǔ)中的信息以及從其他進(jìn)程獲得的信息設(shè)置對(duì)象的值,包括兩階段提交協(xié)議有關(guān)對(duì)象的值。當(dāng)一個(gè)處理器出現(xiàn)故障時(shí),服務(wù)器也會(huì)崩潰,這樣它就不會(huì)發(fā)送錯(cuò)誤的信息或?qū)㈠e(cuò)誤的值寫(xiě)入持久存儲(chǔ),即它不會(huì)產(chǎn)生隨機(jī)故障。服務(wù)器崩潰可能出現(xiàn)在任何時(shí)候,特別是在恢復(fù)時(shí)也可能出現(xiàn)。

  • 消息傳遞可能有任意長(zhǎng)的延遲。消息可能丟失、重復(fù)或者損壞。接收方(通過(guò)校驗(yàn)和)能夠檢測(cè)到受損消息。未發(fā)現(xiàn)的受損消息和偽造的消息可能會(huì)導(dǎo)致災(zāi)難性故障。

利用這個(gè)關(guān)于持久性存儲(chǔ)、處理器和通信的故障模型能夠設(shè)計(jì)出一個(gè)可靠系統(tǒng),該系統(tǒng)的組件可對(duì)付任何單一故障,并提供一個(gè)簡(jiǎn)單的故障模型。特別是,可靠存儲(chǔ)(stable storage)可以在出現(xiàn)一個(gè)write操作故障或者進(jìn)程崩潰的情況下提供原子寫(xiě)操作。它是通過(guò)將每一個(gè)數(shù)據(jù)塊復(fù)制到兩個(gè)磁盤(pán)上實(shí)現(xiàn)的。此時(shí)一個(gè)write操作用于兩個(gè)磁盤(pán)塊,在一個(gè)磁盤(pán)出現(xiàn)故障的前提下,另一個(gè)好的磁盤(pán)也可以提供正確數(shù)據(jù)。可靠處理器(stable processor)使用可靠存儲(chǔ),用于在崩潰之后恢復(fù)對(duì)象??赏ㄟ^(guò)可靠的遠(yuǎn)程過(guò)程調(diào)用機(jī)制來(lái)屏蔽通信錯(cuò)誤。

3.2、兩階段提交協(xié)議的超時(shí)

在兩階段協(xié)議的不同階段,協(xié)調(diào)者或參與者都會(huì)遇到這種場(chǎng)景:不能處理它的那部分協(xié)議,直到接收到下一個(gè)請(qǐng)求或應(yīng)答為止。

首先考慮這樣的情形:某個(gè)投票者投Yes票并等待協(xié)調(diào)者發(fā)回最終決定,即告訴它是提交事務(wù)還是放棄事務(wù)。這樣參與者的結(jié)果是不確定(uncertain)的,它在協(xié)調(diào)者處得到投票結(jié)果之前不能進(jìn)行進(jìn)一步處理。參與者不能單方面決定下一步做什么,同時(shí)該事務(wù)使用的對(duì)象也不能釋放以用于其他事物。參與者向協(xié)調(diào)者發(fā)出getDecision請(qǐng)求來(lái)獲取事務(wù)的結(jié)果,直到收到應(yīng)答時(shí),才能進(jìn)入兩階段協(xié)議的第二階段。

同理,如果協(xié)調(diào)者發(fā)生故障,那么參與者將不能獲得協(xié)定,直到協(xié)調(diào)者被替代為止,這可能導(dǎo)致不確定狀態(tài)的參與者長(zhǎng)時(shí)間的延遲。

不依賴協(xié)調(diào)者獲取最終決定的方法是通過(guò)參與者協(xié)作來(lái)獲得決定。這種策略的優(yōu)點(diǎn)是可以在協(xié)調(diào)者出故障時(shí)使用。

4、兩階段提交的故障處理

  • 當(dāng)參與者發(fā)生故障的時(shí)候:

如何理解Java分布式事務(wù)
  • 當(dāng)協(xié)調(diào)者發(fā)生故障的時(shí)候:

如何理解Java分布式事務(wù)

5、兩階段提交的性能

假設(shè)一切運(yùn)轉(zhuǎn)正常,即協(xié)調(diào)者參與者不出現(xiàn)故障,通信也正常時(shí),有N個(gè)參與者的兩階段提交協(xié)議需要N個(gè)canCommit消息和應(yīng)答,然后再有N個(gè)doCommit消息。這樣消息開(kāi)銷和3N成正比,時(shí)間開(kāi)銷是3次消息往返。由于協(xié)議在沒(méi)有haveCommitted消息時(shí)仍可以正常運(yùn)作(它們的作用只是通知服務(wù)器刪除過(guò)時(shí)的協(xié)調(diào)者消息),因此在估計(jì)協(xié)議開(kāi)銷上,不將haveCommitted消息計(jì)算在內(nèi)。

在最壞的情況下,兩階段提交協(xié)議在執(zhí)行過(guò)程中可能出現(xiàn)任意多次服務(wù)器和通信故障。盡管協(xié)議不能指定協(xié)議完成的時(shí)間限制,但它能正確處理連續(xù)故障(服務(wù)崩潰或者消息丟失),并保證最終完成。

6、使用消息隊(duì)列來(lái)避免分布式事務(wù)

5.1、消息隊(duì)列

由于分布式事務(wù)存在嚴(yán)重的性能問(wèn)題,在設(shè)計(jì)高并發(fā)服務(wù)的時(shí)候,往往通過(guò)其他途徑來(lái)解決數(shù)據(jù)一致性問(wèn)題。

舉例來(lái)講,你在北京很有名的姚記炒肝點(diǎn)了炒肝并付了錢(qián)后,他們并不會(huì)直接把你點(diǎn)的炒肝給你,而是給你一張小票,然后讓你拿著小票到出貨區(qū)排隊(duì)去取。為什么他們要將付錢(qián)和取貨兩個(gè)動(dòng)作分開(kāi)呢?原因很多,其中一個(gè)很重要的原因是為了使他們接待能力增強(qiáng)(并發(fā)量更高)。

還是回到我們的問(wèn)題,只要這張小票在,你最終是能拿到炒肝的。同理轉(zhuǎn)賬服務(wù)也是如此,當(dāng)支付寶賬戶扣除1萬(wàn)后,我們只要生成一個(gè)憑證(消息)即可,這個(gè)憑證(消息)上寫(xiě)著“讓余額寶賬戶增加 1萬(wàn)”,只要這個(gè)憑證(消息)能可靠保存,我們最終是可以拿著這個(gè)憑證(消息)讓余額寶賬戶增加1萬(wàn)的,即我們能依靠這個(gè)憑證(消息)完成最終一致性。

這樣我們上述的轉(zhuǎn)賬就變成了如下過(guò)程:

  • 支付寶在扣款事務(wù)提交之前,向消息隊(duì)列發(fā)送消息。此時(shí)的消息隊(duì)列只記錄消息,而并沒(méi)有將消息發(fā)往余額寶。

  • 當(dāng)支付寶扣款事務(wù)提交成功,向消息隊(duì)列發(fā)送確認(rèn)。在得到確認(rèn)的指令后,消息隊(duì)列向該消息發(fā)往余額寶。

  • 當(dāng)支付寶扣款事務(wù)提交失敗,向消息隊(duì)列發(fā)送取消。在得到取消的指令后,消息隊(duì)列取消該消息,該消息將不會(huì)被發(fā)送。

  • 對(duì)于那么未確認(rèn)的消息,需要消息隊(duì)列去支付寶系統(tǒng)查詢這個(gè)消息的狀態(tài),并進(jìn)行更新。(因?yàn)橹Ц秾毧赡茉诳劭钍聞?wù)提交成功后掛掉,此時(shí)消息的狀態(tài)未被更新為:“確認(rèn)發(fā)送“。從而導(dǎo)致消息不能被發(fā)送。

5.2、重復(fù)投遞

還有一個(gè)嚴(yán)重的問(wèn)題是消息重復(fù)投遞,以我們支付寶轉(zhuǎn)賬到余額寶為例,如果相同的消息被重復(fù)投遞兩次,那么我們余額寶賬戶將會(huì)增加2萬(wàn)而不是1萬(wàn)了。

以上就是“如何理解Java分布式事務(wù)”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會(huì)為大家更新不同的知識(shí),如果還想學(xué)習(xí)更多的知識(shí),請(qǐng)關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(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)容。

AI