這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)?lái)有關(guān)基于消息隊(duì)列的分布式事務(wù)解決方案是什么,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
創(chuàng)新互聯(lián)建站咨詢熱線:18982081108,為您提供成都網(wǎng)站建設(shè)網(wǎng)頁(yè)設(shè)計(jì)及定制高端網(wǎng)站建設(shè)服務(wù),創(chuàng)新互聯(lián)建站網(wǎng)頁(yè)制作領(lǐng)域十余年,包括發(fā)電機(jī)租賃等多個(gè)方面擁有多年的網(wǎng)站運(yùn)維經(jīng)驗(yàn),選擇創(chuàng)新互聯(lián)建站,為網(wǎng)站保駕護(hù)航!
在我們還在“牙牙學(xué)語(yǔ)”的時(shí)候,老師經(jīng)常會(huì)通過(guò)轉(zhuǎn)賬的栗子來(lái)跟我們講解事務(wù),但跟這里場(chǎng)景不一樣的是,老師講的是本地事務(wù),而這里面對(duì)的是分布式事務(wù)!我們先來(lái)簡(jiǎn)單回顧一下本地事務(wù)!
?? 談到本地事務(wù),大家可能都很熟悉,因?yàn)檫@個(gè)數(shù)據(jù)庫(kù)引擎層面能支持的!所以也稱數(shù)據(jù)庫(kù)事務(wù),數(shù)據(jù)庫(kù)事務(wù)四大特征:原子性(A),一致性(C),隔離性(I)和持久性(D),而在這四大特性中,我認(rèn)為一致性是最基本的特性,其它的三個(gè)特性都為了保證一致性而存在的!
?? 回到學(xué)生時(shí)代老師給我們舉的經(jīng)典栗子,A賬戶給B賬戶轉(zhuǎn)賬100元(A、B處于同一個(gè)庫(kù)中),如果A的賬戶發(fā)生扣款,B的賬戶卻沒(méi)有到賬,這就出現(xiàn)了數(shù)據(jù)的不一致!為了保證數(shù)據(jù)的一致性,數(shù)據(jù)庫(kù)的事務(wù)機(jī)制會(huì)讓A賬戶扣款和B在賬戶到賬的兩個(gè)操作要么同時(shí)成功,如果有一個(gè)操作失敗,則多個(gè)操作同時(shí)回滾,這就是事務(wù)的原子性,為了保證事務(wù)操作的原子性,就必須實(shí)現(xiàn)基于日志的REDO/UNDO機(jī)制!但是,僅有原子性還不夠,因?yàn)槲覀兊南到y(tǒng)是運(yùn)行在多線程環(huán)境下,如果多個(gè)事務(wù)并行,即使保證了每一個(gè)事務(wù)的原子性,仍然會(huì)出現(xiàn)數(shù)據(jù)不一致的情況。例如A賬戶原來(lái)有200元的余額, A賬戶給B賬戶轉(zhuǎn)賬100元,先讀取A賬戶的余額,然后在這個(gè)值上減去100元,但是在這兩個(gè)操作之間,A賬戶又給C賬戶轉(zhuǎn)賬100元,那么最后的結(jié)果應(yīng)該是A減去了200元。但事實(shí)上,A賬戶給B賬戶最終完成轉(zhuǎn)賬后,A賬戶只減掉了100元,因?yàn)锳賬戶向C賬戶轉(zhuǎn)賬減掉的100元被覆蓋了!所以為了保證并發(fā)情況下的一致性,又引入的隔離性,即多個(gè)事務(wù)并發(fā)執(zhí)行后的狀態(tài),和它們串行執(zhí)行后的狀態(tài)是等價(jià)的!隔離性又有多種隔離級(jí)別,為了實(shí)現(xiàn)隔離性(最終都是為了保證一致性)數(shù)據(jù)庫(kù)又引入了悲觀鎖、樂(lè)觀鎖等等……本文的主題是分布式事務(wù),所以本地事務(wù)就只是簡(jiǎn)單回顧一下,需要記住的一點(diǎn)是,事務(wù)是為了保證數(shù)據(jù)的一致性!
??還記得剛畢業(yè)那年,帶著滿腔的熱血就去到了一家互聯(lián)網(wǎng)公司,領(lǐng)導(dǎo)給我的第一個(gè)任務(wù)就是在列表上增加一個(gè)修改數(shù)據(jù)的功能。這能難倒我?我分分鐘給你搞出來(lái)!不就是在列表上增加了一個(gè)“修改”按鈕,點(diǎn)擊按鈕彈出框修改后保存就好了么。然而一切不像我想象的那么順利,點(diǎn)擊保存并刷新列表后,頁(yè)面上的數(shù)據(jù)還是顯示的修改之前的內(nèi)容,像沒(méi)有修改成功一樣!過(guò)一會(huì)兒再刷新列表,數(shù)據(jù)就能正常顯示了!測(cè)試多次之后都是這樣!沒(méi)見(jiàn)過(guò)什么大場(chǎng)面的我開(kāi)始有點(diǎn)慌了,是我哪里寫得不對(duì)么?最終,我不得不求助組內(nèi)經(jīng)驗(yàn)比較豐富的前輩!他深吸了一口氣告訴我說(shuō):“畢竟是剛畢業(yè)的小伙子??!我來(lái)跟你講講原因吧!我們的數(shù)據(jù)庫(kù)是做了讀寫分離的,部分讀庫(kù)與寫庫(kù)在不同的網(wǎng)絡(luò)分區(qū)。你的數(shù)據(jù)更新到了寫庫(kù),而讀數(shù)據(jù)的時(shí)候是從讀庫(kù)讀取的。更新到寫庫(kù)的數(shù)據(jù)同步到讀庫(kù)是有一定的延遲的,也就是說(shuō)讀庫(kù)與寫庫(kù)會(huì)有短暫的數(shù)據(jù)不一致”!“這樣不會(huì)體驗(yàn)不好么?為什么不能做到寫入的數(shù)據(jù)立馬能讀出來(lái)?那我這個(gè)功能該怎么實(shí)現(xiàn)呢?” 面對(duì)我的一堆問(wèn)題,同事有些不耐煩的說(shuō):“聽(tīng)說(shuō)過(guò)CAP理論嗎?你先自己去了解一下吧”!是我開(kāi)始查閱各種資料去了解這個(gè)陌生的詞背后的秘密!
??CAP理論是由加州大學(xué)Eric Brewer教授提出來(lái)的,這個(gè)理論告訴我們,一個(gè)分布式系統(tǒng)不可能同時(shí)滿足一致性(Consistency)、可用性(Availability)、分區(qū)容錯(cuò)性(Partition tolerance)這三個(gè)基本需求,最多只能同時(shí)滿足其中兩項(xiàng)。
??一致性:這里的一致性是指數(shù)據(jù)的強(qiáng)一致,也稱為線性一致性。是指在分布式環(huán)境中,數(shù)據(jù)在多個(gè)副本之間是否能夠保持一致的特性。也就是說(shuō)對(duì)某個(gè)數(shù)據(jù)進(jìn)行寫操作后立馬執(zhí)行讀操作,必須能讀取到剛剛寫入的值。(any read operation that begins after a write operation completes must return that value, or the result of a later write operation) ??可用性:任意被無(wú)故障節(jié)點(diǎn)接收到的請(qǐng)求,必須能夠在有限的時(shí)間內(nèi)響應(yīng)結(jié)果。(every request received by a non-failing node in the system must result in a response) ??分區(qū)容錯(cuò)性:如果集群中的機(jī)器被分成了兩部分,這兩部分不能互相通信,系統(tǒng)是否能繼續(xù)正常工作。(the network will be allowed to lose arbitrarily many messages sent from one node to another)
??在分布式系統(tǒng)中,分區(qū)容錯(cuò)性是基本要保證的。也就是說(shuō)只能在一致性和可用性之間進(jìn)行取舍。一致性和可用性,為什么不可能同時(shí)成立?回到之前修改列表的例子,由于數(shù)據(jù)會(huì)分布在不同的網(wǎng)絡(luò)分區(qū),必然會(huì)存在數(shù)據(jù)同步的問(wèn)題,而同步會(huì)存在網(wǎng)絡(luò)延遲、異常等問(wèn)題,所以會(huì)出現(xiàn)數(shù)據(jù)的不一致!如果要保證數(shù)據(jù)的一致性,那么就必須在對(duì)寫庫(kù)進(jìn)行操作時(shí),鎖定其他讀庫(kù)的操作。只有寫入成功且完成數(shù)據(jù)同步后,才能重新放開(kāi)讀寫,而這樣在鎖定期間,系統(tǒng)喪失了可用性。更詳細(xì)關(guān)于CAP理論可以參考這篇文章(https://mwhittaker.github.io/blog/an_illustrated_proof_of_the_cap_theorem/),該文章講得比較通俗易懂!
?? 分布式事務(wù)就是在分布式的場(chǎng)景下,需要滿足事務(wù)的需求!上篇文章我們聊過(guò)了消息中間件,那這篇文章我們要聊的是分布式事務(wù),把兩者一結(jié)合,便有了基于消息中間件的分布式事務(wù)解決方案!不管是本地事務(wù),還是分布式事務(wù),都是為了解決數(shù)據(jù)的一致性問(wèn)題!一致性這個(gè)詞咱們前面多次提及!與本地事務(wù)不同的是,分布式事務(wù)需要保證的是分布式環(huán)境下,不同數(shù)據(jù)庫(kù)表中的數(shù)據(jù)的一致性問(wèn)題。分布式事務(wù)的解決方案有多種,如XA協(xié)議、TCC三階段提交、基于消息隊(duì)列等等,本文只會(huì)涉及基于消息隊(duì)列的解決方案!
?? 本地事務(wù)講到了一致性,分布式事務(wù)不可避免的面臨著一致性的問(wèn)題!回到最開(kāi)始跨行轉(zhuǎn)賬的例子,如果A銀行用戶向B銀行用戶轉(zhuǎn)賬,正常流程應(yīng)該是:
1、A銀行對(duì)轉(zhuǎn)出賬戶執(zhí)行檢查校驗(yàn),進(jìn)行金額扣減。
2、A銀行同步調(diào)用B銀行轉(zhuǎn)賬接口。
3、B銀行對(duì)轉(zhuǎn)入賬戶進(jìn)行檢查校驗(yàn),進(jìn)行金額增加。
4、B銀行返回處理結(jié)果給A銀行。
??
?? 在正常情況對(duì)一致性要求不高的場(chǎng)景,這樣的設(shè)計(jì)是可以滿足需求的。但是像銀行這樣的系統(tǒng),如果這樣實(shí)現(xiàn)大概早就破產(chǎn)了吧。我們先看看這樣的設(shè)計(jì)最主要的問(wèn)題:
1、同步調(diào)用遠(yuǎn)程接口,如果接口比較耗時(shí),會(huì)導(dǎo)致主線程阻塞時(shí)間較長(zhǎng)。
2、流量不能很好控制,A銀行系統(tǒng)的流量高峰可能壓垮B銀行系統(tǒng)(當(dāng)然B銀行肯定會(huì)有自己的限流機(jī)制)。
3、如果“第1步”剛執(zhí)行完,系統(tǒng)由于某種原因宕機(jī)了,那會(huì)導(dǎo)致A銀行賬戶扣款了,但是B銀行沒(méi)有收到接口的調(diào)用,這就出現(xiàn)了兩個(gè)系統(tǒng)數(shù)據(jù)的不一致。
4、如果在執(zhí)行“第3步”后,B銀行由于某種原因宕機(jī)了而無(wú)法正確回應(yīng)請(qǐng)求(實(shí)際上轉(zhuǎn)賬操作在B銀行系統(tǒng)已經(jīng)執(zhí)行且入庫(kù)),這時(shí)候A銀行等待接口響應(yīng)會(huì)異常,誤以為轉(zhuǎn)賬失敗而回滾“第1步”操作,這也會(huì)出現(xiàn)了兩個(gè)系統(tǒng)數(shù)據(jù)的不一致。
?? 對(duì)于問(wèn)題的1、2都很好解決,如果對(duì)消息隊(duì)列熟悉的朋友應(yīng)該很快能想到可以引入消息中間件進(jìn)行異步和削峰處理,于是又重新設(shè)計(jì)了一個(gè)方案,流程如下:
1、A銀行對(duì)賬戶進(jìn)行檢查校驗(yàn),進(jìn)行金額扣減。
2、將對(duì)B銀行的請(qǐng)求異步寫入隊(duì)列,主線程返回。
3、啟動(dòng)后臺(tái)程序從隊(duì)列獲取待處理數(shù)據(jù)。
4、后臺(tái)程序?qū)銀行接口進(jìn)行遠(yuǎn)程調(diào)用。
5、B銀行對(duì)轉(zhuǎn)入賬戶進(jìn)行檢查校驗(yàn),進(jìn)行金額增加。
6、B銀行處理完成回調(diào)A銀行接口通知處理結(jié)果。
??
?? 通過(guò)上面的圖我們能看到,引入消息隊(duì)列后,系統(tǒng)的復(fù)雜性瞬間提升了,雖然彌補(bǔ)了我們第一種方案的幾個(gè)不足點(diǎn),但也帶來(lái)了更多的問(wèn)題,比如消息隊(duì)列系統(tǒng)本身的可用性、消息隊(duì)列的延遲等等!并且,這樣的設(shè)計(jì)依然沒(méi)有解決我們面臨的核心問(wèn)題-數(shù)據(jù)的一致性!
1、如果“第1步”剛執(zhí)行完,系統(tǒng)由于某種原因宕機(jī)了,那會(huì)導(dǎo)致A銀行賬戶扣款了,但是寫入消息隊(duì)列失敗,無(wú)法進(jìn)行B銀行接口調(diào)用,從而導(dǎo)致數(shù)據(jù)不一致。
2、如果B銀行在執(zhí)行“第5步”時(shí)由于校驗(yàn)失敗而未能成功轉(zhuǎn)賬,在回調(diào)A銀行接口通知回滾時(shí)網(wǎng)絡(luò)異?;蛘咤礄C(jī),會(huì)導(dǎo)致A銀行轉(zhuǎn)賬無(wú)法完成回滾,從而導(dǎo)致數(shù)據(jù)不一致。
?? 面對(duì)上述問(wèn)題,我們不得不對(duì)系統(tǒng)再次進(jìn)行升級(jí)改造。為了解決“A銀行賬戶扣款了,但是寫入消息隊(duì)列失敗”的問(wèn)題,我們需要借助一個(gè)轉(zhuǎn)賬日志表,或者叫轉(zhuǎn)賬流水表,該表簡(jiǎn)單的設(shè)計(jì)如下:
字段名稱 | 字段描述 |
---|---|
tId | 交易流水id |
accountNo | 轉(zhuǎn)出賬戶卡號(hào) |
targetBankNo | 目標(biāo)銀行編碼 |
targetAccountNo | 目標(biāo)銀行卡號(hào) |
amount | 交易金額 |
status | 交易狀態(tài)(待處理、處理成功、處理失?。?/td> |
lastUpdateTime | 最后更新時(shí)間 |
?? 這個(gè)流水表需要怎么用呢?我們?cè)凇暗?步”進(jìn)行扣款時(shí),同時(shí)往流水表寫入一條操作流水,狀態(tài)為“待處理”,并且這兩個(gè)操作必須是原子的,也就是說(shuō)必須通過(guò)本地事務(wù)保證這兩個(gè)操作要么同時(shí)成功,要么同時(shí)失??!這就保證了只要轉(zhuǎn)賬扣款成功,必定會(huì)記錄一條狀態(tài)為“待處理”的轉(zhuǎn)賬流水。如果在這一步失敗了,那自然就是轉(zhuǎn)賬失敗,沒(méi)有后續(xù)操作了。如果這步操作后系統(tǒng)宕機(jī)了導(dǎo)致沒(méi)有將消息成功寫入消息隊(duì)列(也就是“第2步”)也沒(méi)關(guān)系,因?yàn)槲覀兊牧魉當(dāng)?shù)據(jù)已經(jīng)持久化了!這時(shí)候我們只需要加入一個(gè)后臺(tái)線程進(jìn)行補(bǔ)償,定期的從轉(zhuǎn)賬流水表中讀取狀態(tài)為“待處理”且最后更新的時(shí)間距當(dāng)前時(shí)間大于某個(gè)閾值的數(shù)據(jù),重新放入消息隊(duì)列進(jìn)行補(bǔ)償。這樣,就保證了消息即使丟失,也會(huì)有補(bǔ)償機(jī)制!B銀行在處理完轉(zhuǎn)賬請(qǐng)求后會(huì)回調(diào)A銀行的接口通知轉(zhuǎn)賬的狀態(tài),從而更新A銀行流水表中的狀態(tài)字段!這樣就完美解決了上一個(gè)方案中的兩個(gè)不足點(diǎn)。系統(tǒng)設(shè)計(jì)圖如下:??
?? 到目前為止,我們很好的解決了消息丟失的問(wèn)題,保證了只要A銀行轉(zhuǎn)賬操作成功,轉(zhuǎn)賬的請(qǐng)求就一定能發(fā)送到B銀行!但是該方案又引入了一個(gè)問(wèn)題,通過(guò)后臺(tái)線程輪詢將消息放入消息隊(duì)列處理,同一次轉(zhuǎn)賬請(qǐng)求可能會(huì)出現(xiàn)多次放入消息隊(duì)列而多次消費(fèi)的情況,這樣B銀行會(huì)對(duì)同一轉(zhuǎn)賬多次處理導(dǎo)致數(shù)據(jù)出現(xiàn)不一致!那怎么保證B銀行轉(zhuǎn)賬接口的冪等性呢?
?? 同樣的,我們可以在B銀行系統(tǒng)中需要增加一個(gè)轉(zhuǎn)賬日志表,或者叫轉(zhuǎn)賬流水表,B銀行每次接收到轉(zhuǎn)賬請(qǐng)求,在對(duì)賬戶進(jìn)行操作的時(shí)候同時(shí)往轉(zhuǎn)賬日志表中插入一條轉(zhuǎn)賬日志記錄,同樣這兩個(gè)操作也必須是原子的!在接收到轉(zhuǎn)賬請(qǐng)求后,首先根據(jù)唯一轉(zhuǎn)賬流水Id在日志表中查找判斷該轉(zhuǎn)賬是否已經(jīng)處理過(guò),如果未處理過(guò)則進(jìn)行處理,否則直接回調(diào)返回!最終的架構(gòu)圖如下:??
?? 所以,我們這里最核心的就是A銀行通過(guò)本地事務(wù)保證日志記錄+后臺(tái)線程輪詢保證消息不丟失。B銀行通過(guò)本地事務(wù)保證日志記錄從而保證消息不重復(fù)消費(fèi)!B銀行在回調(diào)A銀行的接口時(shí)會(huì)通知處理結(jié)果,如果轉(zhuǎn)賬失敗,A銀行會(huì)根據(jù)處理結(jié)果進(jìn)行回滾。
當(dāng)然,分布式事務(wù)最好的解決方案是盡量避免出現(xiàn)分布式事務(wù)!
上述就是小編為大家分享的基于消息隊(duì)列的分布式事務(wù)解決方案是什么了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
分享名稱:基于消息隊(duì)列的分布式事務(wù)解決方案是什么
文章來(lái)源:http://vcdvsql.cn/article42/iipshc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供靜態(tài)網(wǎng)站、網(wǎng)站建設(shè)、自適應(yīng)網(wǎng)站、建站公司、品牌網(wǎng)站制作、動(dòng)態(tài)網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)