第一次有人把“分布式事務(wù)”講的這么簡(jiǎn)單明了

不知道你是否遇到過這樣的情況,去小賣鋪買東西樟蠕,付了錢贮聂,但是店主因?yàn)樘幚砹艘恍┢渌拢尤煌浤愀读隋X寨辩,又叫你重新付吓懈。

又或者在網(wǎng)上購物明明已經(jīng)扣款,但是卻告訴我沒有發(fā)生交易靡狞。這一系列情況都是因?yàn)闆]有事務(wù)導(dǎo)致的耻警。這說明了事務(wù)在生活中的一些重要性。

有了事務(wù)甸怕,你去小賣鋪買東西甘穿,那就是一手交錢一手交貨。有了事務(wù)梢杭,你去網(wǎng)上購物温兼,扣款即產(chǎn)生訂單交易。

在進(jìn)入正文之前武契,順便給大家推薦一個(gè)Java架構(gòu)方面的交流學(xué)習(xí)群:180705916募判,里面會(huì)分享一些資深架構(gòu)師錄制的視頻錄像:有Spring,MyBatis咒唆,Netty源碼分析届垫,高并發(fā)、高性能全释、分布式装处、微服務(wù)架構(gòu)的原理,JVM性能優(yōu)化這些成為架構(gòu)師必備的知識(shí)體系恨溜。相信對(duì)于已經(jīng)工作和遇到技術(shù)瓶頸的同學(xué)符衔,在這個(gè)群里會(huì)有你需要的內(nèi)容。有需要的同學(xué)請(qǐng)抓緊時(shí)間加入進(jìn)來糟袁。

事務(wù)的具體定義

事務(wù)提供一種機(jī)制將一個(gè)活動(dòng)涉及的所有操作納入到一個(gè)不可分割的執(zhí)行單元,組成事務(wù)的所有操作只有在所有操作均能正常執(zhí)行的情況下方能提交躺盛,只要其中任一操作執(zhí)行失敗项戴,都將導(dǎo)致整個(gè)事務(wù)的回滾。

簡(jiǎn)單地說槽惫,事務(wù)提供一種“要么什么都不做周叮,要么做全部(All or Nothing)”機(jī)制辩撑。

數(shù)據(jù)庫本地事務(wù)

ACID

說到數(shù)據(jù)庫事務(wù)就不得不說,數(shù)據(jù)庫事務(wù)中的四大特性 ACID:

A:原子性(Atomicity)仿耽,一個(gè)事務(wù)(transaction)中的所有操作合冀,要么全部完成,要么全部不完成项贺,不會(huì)結(jié)束在中間某個(gè)環(huán)節(jié)君躺。

事務(wù)在執(zhí)行過程中發(fā)生錯(cuò)誤,會(huì)被回滾(Rollback)到事務(wù)開始前的狀態(tài)开缎,就像這個(gè)事務(wù)從來沒有執(zhí)行過一樣棕叫。

就像你買東西要么交錢收貨一起都執(zhí)行,要么發(fā)不出貨奕删,就退錢俺泣。

C:一致性(Consistency),事務(wù)的一致性指的是在一個(gè)事務(wù)執(zhí)行之前和執(zhí)行之后數(shù)據(jù)庫都必須處于一致性狀態(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ù)百拓。

打個(gè)比方琴锭,你買東西這個(gè)事情,是不影響其他人的衙传。

D:持久性(Durability)决帖,指的是只要事務(wù)成功結(jié)束,它對(duì)數(shù)據(jù)庫所做的更新就必須永久保存下來蓖捶。

即使發(fā)生系統(tǒng)崩潰地回,重新啟動(dòng)數(shù)據(jù)庫系統(tǒng)后,數(shù)據(jù)庫還能恢復(fù)到事務(wù)成功結(jié)束時(shí)的狀態(tài)。

打個(gè)比方刻像,你買東西的時(shí)候需要記錄在賬本上畅买,即使老板忘記了那也有據(jù)可查。

InnoDB 實(shí)現(xiàn)原理

InnoDB 是 MySQL 的一個(gè)存儲(chǔ)引擎细睡,大部分人對(duì) MySQL 都比較熟悉谷羞,這里簡(jiǎn)單介紹一下數(shù)據(jù)庫事務(wù)實(shí)現(xiàn)的一些基本原理。

在本地事務(wù)中溜徙,服務(wù)和資源在事務(wù)的包裹下可以看做是一體的湃缎,如下圖:

我們的本地事務(wù)由資源管理器進(jìn)行管理:

而事務(wù)的 ACID 是通過 InnoDB 日志和鎖來保證。事務(wù)的隔離性是通過數(shù)據(jù)庫鎖的機(jī)制實(shí)現(xiàn)的萌京,持久性通過 Redo Log(重做日志)來實(shí)現(xiàn)雁歌,原子性和一致性通過 Undo Log 來實(shí)現(xiàn)。

Undo Log 的原理很簡(jiǎn)單知残,為了滿足事務(wù)的原子性靠瞎,在操作任何數(shù)據(jù)之前,首先將數(shù)據(jù)備份到一個(gè)地方(這個(gè)存儲(chǔ)數(shù)據(jù)備份的地方稱為 Undo Log)求妹。然后進(jìn)行數(shù)據(jù)的修改乏盐。

如果出現(xiàn)了錯(cuò)誤或者用戶執(zhí)行了 Rollback 語句,系統(tǒng)可以利用 Undo Log 中的備份將數(shù)據(jù)恢復(fù)到事務(wù)開始之前的狀態(tài)制恍。

和 Undo Log 相反父能,Redo Log 記錄的是新數(shù)據(jù)的備份。在事務(wù)提交前净神,只要將 Redo Log 持久化即可何吝,不需要將數(shù)據(jù)持久化。

當(dāng)系統(tǒng)崩潰時(shí)鹃唯,雖然數(shù)據(jù)沒有持久化爱榕,但是 Redo Log 已經(jīng)持久化。系統(tǒng)可以根據(jù) Redo Log 的內(nèi)容坡慌,將所有數(shù)據(jù)恢復(fù)到最新的狀態(tài)黔酥。對(duì)具體實(shí)現(xiàn)過程有興趣的同學(xué)可以去自行搜索擴(kuò)展。

分布式事務(wù)

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

分布式事務(wù)指事務(wù)的參與者洪橘、支持事務(wù)的服務(wù)器跪者、資源服務(wù)器以及事務(wù)管理器分別位于不同的分布式系統(tǒng)的不同節(jié)點(diǎn)之上。

簡(jiǎn)單的說熄求,就是一次大的操作由不同的小操作組成渣玲,這些小的操作分布在不同的服務(wù)器上,且屬于不同的應(yīng)用抡四,分布式事務(wù)需要保證這些小操作要么全部成功柜蜈,要么全部失敗仗谆。

本質(zhì)上來說指巡,分布式事務(wù)就是為了保證不同數(shù)據(jù)庫的數(shù)據(jù)一致性淑履。

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

從上面本地事務(wù)來看,我們可以分為兩塊:

Service 產(chǎn)生多個(gè)節(jié)點(diǎn)

Resource 產(chǎn)生多個(gè)節(jié)點(diǎn)

Service 多個(gè)節(jié)點(diǎn)

隨著互聯(lián)網(wǎng)快速發(fā)展藻雪,微服務(wù)秘噪,SOA 等服務(wù)架構(gòu)模式正在被大規(guī)模的使用。

舉個(gè)簡(jiǎn)單的例子勉耀,一個(gè)公司之內(nèi)指煎,用戶的資產(chǎn)可能分為好多個(gè)部分,比如余額便斥,積分至壤,優(yōu)惠券等等。

在公司內(nèi)部有可能積分功能由一個(gè)微服務(wù)團(tuán)隊(duì)維護(hù)枢纠,優(yōu)惠券又是另外的團(tuán)隊(duì)維護(hù)像街。

這樣的話就無法保證積分扣減了之后,優(yōu)惠券能否扣減成功晋渺。

Resource多個(gè)節(jié)點(diǎn)

同樣的镰绎,互聯(lián)網(wǎng)發(fā)展得太快了,我們的 MySQL 一般來說裝千萬級(jí)的數(shù)據(jù)就得進(jìn)行分庫分表木西。

對(duì)于一個(gè)支付寶的轉(zhuǎn)賬業(yè)務(wù)來說畴栖,你給朋友轉(zhuǎn)錢,有可能你的數(shù)據(jù)庫是在北京八千,而你的朋友的錢是存在上海吗讶,所以我們依然無法保證他們能同時(shí)成功。

分布式事務(wù)的基礎(chǔ)

從上面來看分布式事務(wù)是隨著互聯(lián)網(wǎng)高速發(fā)展應(yīng)運(yùn)而生的恋捆,這是一個(gè)必然照皆。

我們之前說過數(shù)據(jù)庫的 ACID 四大特性,已經(jīng)無法滿足我們分布式事務(wù)鸠信,這個(gè)時(shí)候又有一些新的大佬提出一些新的理論纵寝。

CAP

CAP 定理,又被叫作布魯爾定理星立。對(duì)于設(shè)計(jì)分布式系統(tǒng)(不僅僅是分布式事務(wù))的架構(gòu)師來說爽茴,CAP 就是你的入門理論。

C (一致性):對(duì)某個(gè)指定的客戶端來說绰垂,讀操作能返回最新的寫操作室奏。

對(duì)于數(shù)據(jù)分布在不同節(jié)點(diǎn)上的數(shù)據(jù)來說,如果在某個(gè)節(jié)點(diǎn)更新了數(shù)據(jù)劲装,那么在其他節(jié)點(diǎn)如果都能讀取到這個(gè)最新的數(shù)據(jù)胧沫,那么就稱為強(qiáng)一致昌简,如果有某個(gè)節(jié)點(diǎn)沒有讀取到,那就是分布式不一致绒怨。

A (可用性):非故障的節(jié)點(diǎn)在合理的時(shí)間內(nèi)返回合理的響應(yīng)(不是錯(cuò)誤和超時(shí)的響應(yīng))纯赎。可用性的兩個(gè)關(guān)鍵一個(gè)是合理的時(shí)間南蹂,一個(gè)是合理的響應(yīng)犬金。

合理的時(shí)間指的是請(qǐng)求不能無限被阻塞,應(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è)比方策彤,這里集群有多臺(tái)機(jī)器栓袖,有臺(tái)機(jī)器網(wǎng)絡(luò)出現(xiàn)了問題,但是這個(gè)集群仍然可以正常工作锅锨。

熟悉 CAP 的人都知道叽赊,三者不能共有,如果感興趣可以搜索 CAP 的證明必搞,在分布式系統(tǒng)中必指,網(wǎng)絡(luò)無法 100% 可靠,分區(qū)其實(shí)是一個(gè)必然現(xiàn)象恕洲。

如果我們選擇了 CA 而放棄了 P塔橡,那么當(dāng)發(fā)生分區(qū)現(xiàn)象時(shí),為了保證一致性霜第,這個(gè)時(shí)候必須拒絕請(qǐng)求葛家,但是 A 又不允許,所以分布式系統(tǒng)理論上不可能選擇 CA 架構(gòu)泌类,只能選擇 CP 或者 AP 架構(gòu)癞谒。

對(duì)于 CP 來說,放棄可用性刃榨,追求一致性和分區(qū)容錯(cuò)性弹砚,我們的 ZooKeeper 其實(shí)就是追求的強(qiáng)一致。

對(duì)于 AP 來說枢希,放棄一致性(這里說的一致性是強(qiáng)一致性)桌吃,追求分區(qū)容錯(cuò)性和可用性,這是很多分布式系統(tǒng)設(shè)計(jì)時(shí)的選擇苞轿,后面的 BASE 也是根據(jù) AP 來擴(kuò)展茅诱。

順便一提逗物,CAP 理論中是忽略網(wǎng)絡(luò)延遲,也就是當(dāng)事務(wù)提交時(shí)瑟俭,從節(jié)點(diǎn) A 復(fù)制到節(jié)點(diǎn) B 沒有延遲翎卓,但是在現(xiàn)實(shí)中這個(gè)是明顯不可能的,所以總會(huì)有一定的時(shí)間是不一致尔当。

同時(shí) CAP 中選擇兩個(gè)莲祸,比如你選擇了 CP蹂安,并不是叫你放棄 A椭迎。因?yàn)?P 出現(xiàn)的概率實(shí)在是太小了,大部分的時(shí)間你仍然需要保證 CA田盈。

就算分區(qū)出現(xiàn)了你也要為后來的 A 做準(zhǔn)備畜号,比如通過一些日志的手段,是其他機(jī)器回復(fù)至可用允瞧。

BASE

BASE 是 Basically Available(基本可用)简软、Soft state(軟狀態(tài))和 Eventually consistent (最終一致性)三個(gè)短語的縮寫,是對(duì) CAP 中 AP 的一個(gè)擴(kuò)展述暂。

基本可用:分布式系統(tǒng)在出現(xiàn)故障時(shí)痹升,允許損失部分可用功能,保證核心功能可用畦韭。

軟狀態(tài):允許系統(tǒng)中存在中間狀態(tài)疼蛾,這個(gè)狀態(tài)不影響系統(tǒng)可用性,這里指的是 CAP 中的不一致艺配。

最終一致:最終一致是指經(jīng)過一段時(shí)間后察郁,所有節(jié)點(diǎn)數(shù)據(jù)都將會(huì)達(dá)到一致。

BASE 解決了 CAP 中理論沒有網(wǎng)絡(luò)延遲转唉,在 BASE 中用軟狀態(tài)和最終一致皮钠,保證了延遲后的一致性。

BASE 和 ACID 是相反的赠法,它完全不同于 ACID 的強(qiáng)一致性模型麦轰,而是通過犧牲強(qiáng)一致性來獲得可用性,并允許數(shù)據(jù)在一段時(shí)間內(nèi)是不一致的砖织,但最終達(dá)到一致狀態(tài)款侵。

分布式事務(wù)解決方案

有了上面的理論基礎(chǔ)后,這里開始介紹幾種常見的分布式事務(wù)的解決方案镶苞。

是否真的要分布式事務(wù)

在說方案之前喳坠,首先你一定要明確你是否真的需要分布式事務(wù)?

上面說過出現(xiàn)分布式事務(wù)的兩個(gè)原因茂蚓,其中有個(gè)原因是因?yàn)槲⒎?wù)過多壕鹉。我見過太多團(tuán)隊(duì)一個(gè)人維護(hù)幾個(gè)微服務(wù)剃幌,太多團(tuán)隊(duì)過度設(shè)計(jì),搞得所有人疲勞不堪晾浴。

而微服務(wù)過多就會(huì)引出分布式事務(wù)负乡,這個(gè)時(shí)候我不會(huì)建議你去采用下面任何一種方案,而是請(qǐng)把需要事務(wù)的微服務(wù)聚合成一個(gè)單機(jī)服務(wù)脊凰,使用數(shù)據(jù)庫的本地事務(wù)抖棘。

因?yàn)椴徽撊魏我环N方案都會(huì)增加你系統(tǒng)的復(fù)雜度,這樣的成本實(shí)在是太高了狸涌,千萬不要因?yàn)樽非竽承┰O(shè)計(jì)切省,而引入不必要的成本和復(fù)雜度。

如果你確定需要引入分布式事務(wù)可以看看下面幾種常見的方案帕胆。

2PC

說到 2PC 就不得不聊數(shù)據(jù)庫分布式事務(wù)中的 XA Transactions朝捆。

在 XA 協(xié)議中分為兩階段:

事務(wù)管理器要求每個(gè)涉及到事務(wù)的數(shù)據(jù)庫預(yù)提交(precommit)此操作,并反映是否可以提交懒豹。

事務(wù)協(xié)調(diào)器要求每個(gè)數(shù)據(jù)庫提交數(shù)據(jù)芙盘,或者回滾數(shù)據(jù)。

優(yōu)點(diǎn):

盡量保證了數(shù)據(jù)的強(qiáng)一致脸秽,實(shí)現(xiàn)成本較低儒老,在各大主流數(shù)據(jù)庫都有自己實(shí)現(xiàn),對(duì)于 MySQL 是從 5.5 開始支持记餐。

缺點(diǎn):

單點(diǎn)問題:事務(wù)管理器在整個(gè)流程中扮演的角色很關(guān)鍵驮樊,如果其宕機(jī),比如在第一階段已經(jīng)完成剥扣,在第二階段正準(zhǔn)備提交的時(shí)候事務(wù)管理器宕機(jī)巩剖,資源管理器就會(huì)一直阻塞,導(dǎo)致數(shù)據(jù)庫無法使用钠怯。

同步阻塞:在準(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ò)問題該通知僅被一部分參與者所收到并執(zhí)行了 Commit 操作稳衬,其余的參與者則因?yàn)闆]有收到通知一直處于阻塞狀態(tài)霞捡,這時(shí)候就產(chǎn)生了數(shù)據(jù)的不一致性。

總的來說薄疚,XA 協(xié)議比較簡(jiǎn)單碧信,成本較低赊琳,但是其單點(diǎn)問題,以及不能支持高并發(fā)(由于同步阻塞)依然是其最大的弱點(diǎn)砰碴。

TCC

關(guān)于 TCC(Try-Confirm-Cancel)的概念躏筏,最早是由 Pat Helland 于 2007 年發(fā)表的一篇名為《Life beyond Distributed Transactions:an Apostate’s Opinion》的論文提出。

TCC 事務(wù)機(jī)制相比于上面介紹的 XA呈枉,解決了如下幾個(gè)缺點(diǎn):

解決了協(xié)調(diào)者單點(diǎn)趁尼,由主業(yè)務(wù)方發(fā)起并完成這個(gè)業(yè)務(wù)活動(dòng)。業(yè)務(wù)活動(dòng)管理器也變成多點(diǎn)猖辫,引入集群酥泞。

同步阻塞:引入超時(shí),超時(shí)后進(jìn)行補(bǔ)償住册,并且不會(huì)鎖定整個(gè)資源婶博,將資源轉(zhuǎn)換為業(yè)務(wù)邏輯形式,粒度變小荧飞。

數(shù)據(jù)一致性,有了補(bǔ)償機(jī)制之后名党,由業(yè)務(wù)活動(dòng)管理器控制一致性叹阔。

對(duì)于 TCC 的解釋:

Try 階段:嘗試執(zhí)行,完成所有業(yè)務(wù)檢查(一致性)传睹,預(yù)留必需業(yè)務(wù)資源(準(zhǔn)隔離性)耳幢。

Confirm 階段:確認(rèn)真正執(zhí)行業(yè)務(wù),不作任何業(yè)務(wù)檢查欧啤,只使用 Try 階段預(yù)留的業(yè)務(wù)資源睛藻,Confirm 操作滿足冪等性。要求具備冪等設(shè)計(jì)邢隧,Confirm 失敗后需要進(jìn)行重試店印。

Cancel 階段:取消執(zhí)行,釋放 Try 階段預(yù)留的業(yè)務(wù)資源倒慧,Cancel 操作滿足冪等性按摘。Cancel 階段的異常和 Confirm 階段異常處理方案基本上一致。

舉個(gè)簡(jiǎn)單的例子:如果你用 100 元買了一瓶水纫谅, Try 階段:你需要向你的錢包檢查是否夠 100 元并鎖住這 100 元炫贤,水也是一樣的。

如果有一個(gè)失敗付秕,則進(jìn)行 Cancel(釋放這 100 元和這一瓶水)兰珍,如果 Cancel 失敗不論什么失敗都進(jìn)行重試 Cancel,所以需要保持冪等询吴。

如果都成功掠河,則進(jìn)行 Confirm励幼,確認(rèn)這 100 元被扣,和這一瓶水被賣口柳,如果 Confirm 失敗無論什么失敗則重試(會(huì)依靠活動(dòng)日志進(jìn)行重試)苹粟。

對(duì)于 TCC 來說適合一些:

強(qiáng)隔離性,嚴(yán)格一致性要求的活動(dòng)業(yè)務(wù)跃闹。

執(zhí)行時(shí)間較短的業(yè)務(wù)嵌削。

實(shí)現(xiàn)參考:https://github.com/liuyangming/ByteTCC/。

本地消息表

本地消息表這個(gè)方案最初是 eBay 提出的望艺,eBay 的完整方案 https://queue.acm.org/detail.cfm?id=1394128苛秕。

此方案的核心是將需要分布式處理的任務(wù)通過消息日志的方式來異步執(zhí)行。消息日志可以存儲(chǔ)到本地文本找默、數(shù)據(jù)庫或消息隊(duì)列艇劫,再通過業(yè)務(wù)規(guī)則自動(dòng)或人工發(fā)起重試。

人工重試更多的是應(yīng)用于支付場(chǎng)景惩激,通過對(duì)賬系統(tǒng)對(duì)事后問題的處理店煞。

對(duì)于本地消息隊(duì)列來說核心是把大事務(wù)轉(zhuǎn)變?yōu)樾∈聞?wù)风钻。還是舉上面用 100 元去買一瓶水的例子顷蟀。

1. 當(dāng)你扣錢的時(shí)候,你需要在你扣錢的服務(wù)器上新增加一個(gè)本地消息表骡技,你需要把你扣錢和減去水的庫存寫入到本地消息表鸣个,放入同一個(gè)事務(wù)(依靠數(shù)據(jù)庫本地事務(wù)保證一致性)。

2. 這個(gè)時(shí)候有個(gè)定時(shí)任務(wù)去輪詢這個(gè)本地事務(wù)表布朦,把沒有發(fā)送的消息囤萤,扔給商品庫存服務(wù)器,叫它減去水的庫存是趴,到達(dá)商品服務(wù)器之后涛舍,這時(shí)得先寫入這個(gè)服務(wù)器的事務(wù)表,然后進(jìn)行扣減右遭,扣減成功后做盅,更新事務(wù)表中的狀態(tài)。

3. 商品服務(wù)器通過定時(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í)需要注意重試的冪等足画。

MQ 事務(wù)

在 RocketMQ 中實(shí)現(xiàn)了分布式事務(wù)雄驹,實(shí)際上是對(duì)本地消息表的一個(gè)封裝,將本地消息表移動(dòng)到了 MQ 內(nèi)部淹辞。

下面簡(jiǎn)單介紹一下MQ事務(wù)医舆,如果想對(duì)其詳細(xì)了解可以參考:http://www.reibang.com/p/453c6e7ff81c。

基本流程如下:

第一階段 Prepared 消息象缀,會(huì)拿到消息的地址蔬将。

第二階段執(zhí)行本地事務(wù)。

第三階段通過第一階段拿到的地址去訪問消息攻冷,并修改狀態(tài)娃胆。消息接受者就能使用這個(gè)消息。

如果確認(rèn)消息失敗等曼,在 RocketMQ Broker 中提供了定時(shí)掃描沒有更新狀態(tài)的消息。

如果有消息沒有得到確認(rèn)凿蒜,會(huì)向消息發(fā)送者發(fā)送消息禁谦,來判斷是否提交,在 RocketMQ 中是以 Listener 的形式給發(fā)送者废封,用來處理州泊。

如果消費(fèi)超時(shí),則需要一直重試漂洋,消息接收端需要保證冪等遥皂。如果消息消費(fèi)失敗,這時(shí)就需要人工進(jìn)行處理刽漂,因?yàn)檫@個(gè)概率較低演训,如果為了這種小概率時(shí)間而設(shè)計(jì)這個(gè)復(fù)雜的流程反而得不償失。

Saga 事務(wù)

Saga 是 30 年前一篇數(shù)據(jù)庫倫理提到的一個(gè)概念贝咙。其核心思想是將長(zhǎng)事務(wù)拆分為多個(gè)本地短事務(wù)样悟,由 Saga 事務(wù)協(xié)調(diào)器協(xié)調(diào),如果正常結(jié)束那就正常完成,如果某個(gè)步驟失敗窟她,則根據(jù)相反順序一次調(diào)用補(bǔ)償操作陈症。

Saga 的組成:每個(gè) Saga 由一系列 sub-transaction Ti 組成,每個(gè) Ti 都有對(duì)應(yīng)的補(bǔ)償動(dòng)作 Ci震糖,補(bǔ)償動(dòng)作用于撤銷 Ti 造成的結(jié)果录肯。這里的每個(gè) T,都是一個(gè)本地事務(wù)吊说。

可以看到论咏,和 TCC 相比,Saga 沒有“預(yù)留 try”動(dòng)作疏叨,它的 Ti 就是直接提交到庫潘靖。

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)闆]有鎖住資源愕掏,其他事務(wù)依然可以覆蓋或者影響當(dāng)前事務(wù)度秘。

還是拿 100 元買一瓶水的例子來說,這里定義:

T1 = 扣 100 元饵撑,T2 = 給用戶加一瓶水剑梳,T3 = 減庫存一瓶水。

C1 = 加100元滑潘,C2 = 給用戶減一瓶水垢乙,C3 = 給庫存加一瓶水。

我們一次進(jìn)行 T1语卤,T2追逮,T3 如果發(fā)生問題,就執(zhí)行發(fā)生問題的 C 操作的反向粹舵。

上面說到的隔離性的問題會(huì)出現(xiàn)在钮孵,如果執(zhí)行到 T3 這個(gè)時(shí)候需要執(zhí)行回滾,但是這個(gè)用戶已經(jīng)把水喝了(另外一個(gè)事務(wù))眼滤,回滾的時(shí)候就會(huì)發(fā)現(xiàn)巴席,無法給用戶減一瓶水了。

這就是事務(wù)之間沒有隔離性的問題诅需⊙Γ可以看見 Saga 模式?jīng)]有隔離性的影響還是較大,可以參照華為的解決方案:從業(yè)務(wù)層面入手加入一 Session 以及鎖的機(jī)制來保證能夠串行化操作資源堰塌。

也可以在業(yè)務(wù)層面通過預(yù)先凍結(jié)資金的方式隔離這部分資源毡证, 最后在業(yè)務(wù)操作的過程中可以通過及時(shí)讀取當(dāng)前狀態(tài)的方式獲取到最新的更新。(具體實(shí)例:可以參考華為的 Service Comb)

最后

還是那句話蔫仙,能不用分布式事務(wù)就不用,如果非得使用的話丐箩,結(jié)合自己的業(yè)務(wù)分析摇邦,看看自己的業(yè)務(wù)比較適合哪一種,是在乎強(qiáng)一致屎勘,還是最終一致即可施籍。

最后在總結(jié)一些問題,大家可以下來自己從文章找尋答案:

ACID 和 CAP 的 CA 是一樣的嗎概漱?

分布式事務(wù)常用的解決方案的優(yōu)缺點(diǎn)是什么丑慎?適用于什么場(chǎng)景?

分布式事務(wù)出現(xiàn)的原因?用來解決什么痛點(diǎn)竿裂?

如果想學(xué)習(xí)Java工程化玉吁、高性能及分布式、深入淺出腻异。性能調(diào)優(yōu)进副、Spring,MyBatis悔常,Netty源碼分析的朋友可以加我的Java高級(jí)架構(gòu)進(jìn)階群:180705916影斑,群里有阿里大牛直播講解技術(shù),以及Java大型互聯(lián)網(wǎng)技術(shù)的視頻免費(fèi)分享給大家

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末机打,一起剝皮案震驚了整個(gè)濱河市矫户,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌残邀,老刑警劉巖皆辽,帶你破解...
    沈念sama閱讀 206,723評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蝙叛,死亡現(xiàn)場(chǎng)離奇詭異顽冶,居然都是意外死亡绝淡,警方通過查閱死者的電腦和手機(jī)脐彩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門藏古,熙熙樓的掌柜王于貴愁眉苦臉地迎上來婚度,“玉大人宪祥,你說我怎么就攤上這事臣缀」难眩” “怎么了痹换?”我有些...
    開封第一講書人閱讀 152,998評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)都弹。 經(jīng)常有香客問我娇豫,道長(zhǎng),這世上最難降的妖魔是什么畅厢? 我笑而不...
    開封第一講書人閱讀 55,323評(píng)論 1 279
  • 正文 為了忘掉前任冯痢,我火速辦了婚禮,結(jié)果婚禮上框杜,老公的妹妹穿的比我還像新娘浦楣。我一直安慰自己,他們只是感情好咪辱,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評(píng)論 5 374
  • 文/花漫 我一把揭開白布振劳。 她就那樣靜靜地躺著,像睡著了一般油狂。 火紅的嫁衣襯著肌膚如雪历恐。 梳的紋絲不亂的頭發(fā)上寸癌,一...
    開封第一講書人閱讀 49,079評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音弱贼,去河邊找鬼蒸苇。 笑死,一個(gè)胖子當(dāng)著我的面吹牛哮洽,可吹牛的內(nèi)容都是我干的填渠。 我是一名探鬼主播,決...
    沈念sama閱讀 38,389評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼鸟辅,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼氛什!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起匪凉,我...
    開封第一講書人閱讀 37,019評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤枪眉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后再层,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體贸铜,經(jīng)...
    沈念sama閱讀 43,519評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評(píng)論 2 325
  • 正文 我和宋清朗相戀三年聂受,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蒿秦。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,100評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蛋济,死狀恐怖棍鳖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情碗旅,我是刑警寧澤渡处,帶...
    沈念sama閱讀 33,738評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站祟辟,受9級(jí)特大地震影響医瘫,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜旧困,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評(píng)論 3 307
  • 文/蒙蒙 一醇份、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧吼具,春花似錦被芳、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽剩晴。三九已至锣咒,卻和暖如春侵状,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背毅整。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工趣兄, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人悼嫉。 一個(gè)月前我還...
    沈念sama閱讀 45,547評(píng)論 2 354
  • 正文 我出身青樓艇潭,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親戏蔑。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蹋凝,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容