分布式系統(tǒng)-常見事務(wù)選型

在電商領(lǐng)域等互聯(lián)網(wǎng)場(chǎng)景下电抚,基于CP的強(qiáng)一致性方案在數(shù)據(jù)庫性能和系統(tǒng)處理能力上會(huì)存在一定的瓶頸。所以在互聯(lián)網(wǎng)場(chǎng)景中更多采用柔性事務(wù),所謂的柔性事務(wù)是遵循BASE理論來實(shí)現(xiàn)的事務(wù)模型剧防,它有兩個(gè)特性:基本可用端幼、柔性狀態(tài)。在文中主要基于柔性事務(wù)模型來分析互聯(lián)網(wǎng)產(chǎn)品中分布式事務(wù)的常見解決方案簇宽。

TCC補(bǔ)償型方案

TCC(Try-Confirm-Cancel)是一種比較成熟的分布式數(shù)據(jù)一致性解決方案勋篓,它實(shí)際上是把一個(gè)完整的業(yè)務(wù)拆分為如下三個(gè)步驟。

? Try:這個(gè)階段主要是對(duì)數(shù)據(jù)的校驗(yàn)或者資源的預(yù)留魏割。

? Confirm:確認(rèn)真正執(zhí)行的任務(wù)譬嚣,只操作Try階段預(yù)留的資源。

? Cancel:取消執(zhí)行钞它,釋放Try階段預(yù)留的資源拜银。

其實(shí)TCC是一種兩階段提交的思想殊鞭,第一階段通過Try進(jìn)行準(zhǔn)備工作,第二階段Confirm/Cancel表示Try階段操作的確認(rèn)和回滾盐股。在分布式事務(wù)場(chǎng)景中钱豁,每個(gè)服務(wù)實(shí)現(xiàn)TCC之后,就作為其中的一個(gè)資源疯汁,參與到整個(gè)分布式事務(wù)中牲尺。然后主業(yè)務(wù)服務(wù)在第一階段中分別調(diào)用所有TCC服務(wù)的Try方法。最后根據(jù)第一個(gè)階段的執(zhí)行情況來決定對(duì)第二階段的Confirm或者Cancel幌蚊。

TCC執(zhí)行流程

image.png

例子

在一個(gè)理財(cái)App中谤碳,用戶通過賬戶余額購買一個(gè)理財(cái)產(chǎn)品,這里涉及兩個(gè)事務(wù)操作:

? 在賬戶服務(wù)中溢豆,對(duì)用戶賬戶余額進(jìn)行扣減蜒简。

? 在理財(cái)產(chǎn)品服務(wù)中,對(duì)指定理財(cái)產(chǎn)品可申購金額進(jìn)行扣減漩仙。

這兩個(gè)事務(wù)操作在微服務(wù)架構(gòu)下分別對(duì)應(yīng)的是兩個(gè)不同的微服務(wù)搓茬,以及獨(dú)立的數(shù)據(jù)庫操作,在TCC的工作機(jī)制中队他,首先針對(duì)賬戶服務(wù)和理財(cái)產(chǎn)品服務(wù)分別提供Try卷仑、Confirm和Cancel三個(gè)方法。

? 在賬戶服務(wù)的Try方法中對(duì)實(shí)際申購金額進(jìn)行凍結(jié)麸折,Confirm方法把Try方法凍結(jié)的資金進(jìn)行實(shí)際的扣減锡凝,Cancel方法把Try方法凍結(jié)的資金進(jìn)行解凍。

? 理財(cái)產(chǎn)品服務(wù)的Try方法中將本次申購的部分額度進(jìn)行凍結(jié)垢啼,Confirm方法把Try方法中凍結(jié)的額度進(jìn)行實(shí)際扣減窜锯,Cancel方法把Try方法中凍結(jié)的額度進(jìn)行釋放。

在一個(gè)主業(yè)務(wù)方法中芭析,分別調(diào)用這兩個(gè)服務(wù)對(duì)外提供的處理方法(資金扣減锚扎、理財(cái)產(chǎn)品可申購額度扣減),這兩個(gè)服務(wù)做實(shí)際業(yè)務(wù)處理時(shí)馁启,會(huì)先調(diào)用Try方法來做資源預(yù)留工秩,如果這兩個(gè)方法處理都正常,TCC事務(wù)協(xié)調(diào)器就會(huì)調(diào)用Confirm方法對(duì)預(yù)留資源進(jìn)行實(shí)際應(yīng)用进统。否則TCC事物協(xié)調(diào)器一旦感知到任何一個(gè)服務(wù)的Try方法處理失敗,就會(huì)調(diào)用各個(gè)服務(wù)的Cancel方法進(jìn)行回滾浪听,從而保證數(shù)據(jù)的一致性螟碎。

服務(wù)宕機(jī)或者異常情況的處理方案

TCC事務(wù)框架會(huì)記錄一些分布式事務(wù)的操作日志,保存分布式事務(wù)運(yùn)行的各個(gè)階段和狀態(tài)迹栓。TCC事務(wù)協(xié)調(diào)器會(huì)根據(jù)操作日志來進(jìn)行重試掉分,以達(dá)到數(shù)據(jù)的最終一致性。

需要注意的是,TCC服務(wù)支持接口調(diào)用失敗發(fā)起重試酥郭,所以TCC暴露的接口都需要滿足冪等性华坦。

基于可靠性消息的最終一致性方案

基于可靠性消息的最終一致性是互聯(lián)網(wǎng)公司比較常用的分布式數(shù)據(jù)一致性解決方案,它主要利用消息中間件(Kafka不从、RocketMQ或RabbitMQ)的可靠性機(jī)制來實(shí)現(xiàn)數(shù)據(jù)一致性的投遞惜姐。

例子

以電商平臺(tái)的支付場(chǎng)景為例,用戶完成訂單的支付后不需要同步等待支付結(jié)果椿息,可以繼續(xù)做其他事情歹袁。

但是對(duì)于系統(tǒng)來說,大部分是在發(fā)起支付之后寝优,等到第三方支付平臺(tái)提供異步支付結(jié)果通知条舔,再根據(jù)結(jié)果來設(shè)置該訂單的支付狀態(tài)。

并且如果是支付成功的狀態(tài)乏矾,大部分電商平臺(tái)基于營(yíng)銷策略還會(huì)給賬戶增加一定的積分獎(jiǎng)勵(lì)孟抗。所以,當(dāng)系統(tǒng)接收到第三方返回的支付結(jié)果時(shí)钻心,需要更新支付服務(wù)的支付狀態(tài)凄硼,以及更新賬戶服務(wù)的積分余額,這里就涉及兩個(gè)服務(wù)的數(shù)據(jù)一致性問題扔役。從這個(gè)場(chǎng)景中可以發(fā)現(xiàn)這里的數(shù)據(jù)一致性并不要求實(shí)時(shí)性帆喇,所以我們可以采用基于可靠性消息的最終一致性方案來保證支付服務(wù)和賬戶服務(wù)的數(shù)據(jù)一致性。如圖所示亿胸,支付服務(wù)收到支付結(jié)果通知后坯钦,先更新支付訂單的狀態(tài),再發(fā)送一條消息到分布式消息隊(duì)列中侈玄,賬戶服務(wù)會(huì)監(jiān)聽到指定隊(duì)列的消息并進(jìn)行相應(yīng)的處理婉刀,完成數(shù)據(jù)的同步。(也就是現(xiàn)在主線程更新訂單狀態(tài)序仙,在通過消息通知賬戶服務(wù)更行積分余額<相當(dāng)于異步操作>)

image.png

但是以上操作依舊有原子性問題

就是支付服務(wù)的本地事務(wù)(本地?cái)?shù)據(jù)提交)與發(fā)送消息這個(gè)操作的原子性問題突颊,具體描述如下

? 先發(fā)送消息,再執(zhí)行數(shù)據(jù)庫事務(wù)潘悼,在這種情況下可能會(huì)出現(xiàn)消息發(fā)送成功但是本地事務(wù)更新失敗的情況律秃,仍然會(huì)導(dǎo)致數(shù)據(jù)不一致的問題。

image.png

? 先執(zhí)行數(shù)據(jù)庫事務(wù)操作治唤,再發(fā)送消息棒动,在這種情況下可能會(huì)出現(xiàn)MQ響應(yīng)超時(shí)導(dǎo)致異常,從而將本地事務(wù)回滾宾添,但消息可能已經(jīng)發(fā)送成功了船惨,也會(huì)存在數(shù)據(jù)不一致的問題柜裸。

image.png

解決方案

以上問題也有很多成熟的解決方案,以RocketMQ為例粱锐,它提供了事務(wù)消息模型疙挺,具體的執(zhí)行邏輯如下:

? 生產(chǎn)者發(fā)送一個(gè)事務(wù)消息到消息隊(duì)列上,消息隊(duì)列只記錄這條消息的數(shù)據(jù)怜浅,此時(shí)消費(fèi)者無法消費(fèi)這條消息铐然。

? 生產(chǎn)者執(zhí)行具體的業(yè)務(wù)邏輯,完成本地事務(wù)的操作海雪。

? 接著生產(chǎn)者根據(jù)本地事務(wù)的執(zhí)行結(jié)果發(fā)送一條確認(rèn)消息給消息隊(duì)列服務(wù)器锦爵,如果本地事務(wù)執(zhí)行成功,則發(fā)送一個(gè)Commit消息奥裸,表示在第一步中發(fā)送的消息可以被消費(fèi)险掀,否則,消息隊(duì)列服務(wù)器會(huì)把第一步存儲(chǔ)的消息刪除湾宙。

? 如果生產(chǎn)者在執(zhí)行本地事務(wù)的過程中因?yàn)槟承┣闆r一直未給消息隊(duì)列服務(wù)器發(fā)送確認(rèn)樟氢,那么消息隊(duì)列服務(wù)器會(huì)定時(shí)主動(dòng)回查生產(chǎn)者獲取本地事務(wù)的執(zhí)行結(jié)果,然后根據(jù)回查結(jié)果來決定這條消息是否需要投遞給消費(fèi)者侠鳄。

? 消息隊(duì)列服務(wù)器上存儲(chǔ)的消息被生產(chǎn)者確認(rèn)之后埠啃,消費(fèi)者就可以消費(fèi)這條消息,消息消費(fèi)完成之后發(fā)送一個(gè)確認(rèn)標(biāo)識(shí)給消息隊(duì)列服務(wù)器伟恶,表示該消息投遞成功碴开。

image.png

在RocketMQ事務(wù)消息模型中,事務(wù)是由生產(chǎn)者來完成的博秫,消費(fèi)者不需要考慮潦牛,因?yàn)橄㈥?duì)列可靠性投遞機(jī)制的存在,如果消費(fèi)者沒有簽收該消息挡育,那么消息隊(duì)列服務(wù)器會(huì)重復(fù)投遞巴碗,從而實(shí)現(xiàn)生產(chǎn)者的本地?cái)?shù)據(jù)和消費(fèi)者的本地?cái)?shù)據(jù)在消息隊(duì)列的機(jī)制下達(dá)到最終一致。

不難發(fā)現(xiàn)即寒,在RocketMQ的事務(wù)消息模型中最核心的機(jī)制應(yīng)該是事務(wù)回查橡淆,實(shí)際上查詢模式在很多類似的場(chǎng)景中都可以應(yīng)用。在分布式系統(tǒng)中母赵,由于網(wǎng)絡(luò)通信的存在逸爵,服務(wù)之間的遠(yuǎn)程通信除成功和失敗兩種結(jié)果外,還存在一種未知狀態(tài)凹嘲,比如網(wǎng)絡(luò)超時(shí)痊银。服務(wù)提供者可以提供一個(gè)查詢接口向外部輸出操作的執(zhí)行狀態(tài),服務(wù)調(diào)用方可以通過調(diào)用該接口得知之前操作的結(jié)果并進(jìn)行相應(yīng)的處理施绎。

最大努力通知型

最大努力通知型和基于可靠性消息的最終一致性方案的實(shí)現(xiàn)是類似的溯革,它是一種比較簡(jiǎn)單的柔性事務(wù)解決方案,也比較適用于對(duì)數(shù)據(jù)一致性要求不高的場(chǎng)景谷醉,最典型的使用場(chǎng)景是支付寶支付結(jié)果通知致稀。

image.png

下面站在商戶的角度來分析最大努力通知型的處理過程。

? 商戶先創(chuàng)建一個(gè)支付訂單俱尼,然后調(diào)用支付寶發(fā)起支付請(qǐng)求抖单。

? 支付寶喚醒支付頁面完成支付操作,支付寶同樣會(huì)針對(duì)該商戶創(chuàng)建一個(gè)支付交易遇八,并且根據(jù)用戶的支付結(jié)果記錄支付狀態(tài)矛绘。

? 支付完成后觸發(fā)一個(gè)回調(diào)通知給商戶,商戶收到該通知后刃永,根據(jù)結(jié)果修改本地支付訂單的狀態(tài)货矮,并且返回一個(gè)處理狀態(tài)給支付寶。

? 針對(duì)這個(gè)訂單斯够,在理想狀態(tài)下支付寶的交易狀態(tài)和商戶的交易狀態(tài)會(huì)在通知完成后達(dá)到最終一致囚玫。但是由于網(wǎng)絡(luò)的不確定性,支付結(jié)果通知可能會(huì)失敗或者丟失读规,導(dǎo)致商戶端的支付訂單的狀態(tài)是未知的抓督。所以最大努力通知型的作用就體現(xiàn)了,如果商戶端在收到支付結(jié)果通知后沒有返回一個(gè)“SUCCESS”狀態(tài)碼束亏,那么這個(gè)支付結(jié)果回調(diào)請(qǐng)求會(huì)以衰減重試機(jī)制(逐步拉大通知的間隔)繼續(xù)觸發(fā)铃在,比如1min、5min碍遍、10min定铜、30min……直到達(dá)到最大通知次數(shù)。如果達(dá)到指定次數(shù)后商戶還沒有返回確認(rèn)狀態(tài)雀久,怎么處理呢宿稀?

? 支付寶提供了一個(gè)交易結(jié)果查詢接口,可以根據(jù)這個(gè)支付訂單號(hào)去支付寶查詢支付狀態(tài)赖捌,然后根據(jù)返回的結(jié)果來更新商戶的支付訂單狀態(tài)祝沸,這個(gè)過程可以通過定時(shí)器來觸發(fā),也可以通過人工對(duì)賬來觸發(fā)越庇。

從上述分析可以發(fā)現(xiàn)罩锐,所謂的最大努力通知,就是在商戶端如果沒有返回一個(gè)消息確認(rèn)時(shí)卤唉,支付寶會(huì)不斷地進(jìn)行重試涩惑,直到收到一個(gè)消息確認(rèn)或者達(dá)到最大重試次數(shù)。

不難發(fā)現(xiàn)它的實(shí)現(xiàn)機(jī)制和事務(wù)消息模型的消費(fèi)者消費(fèi)模型類似桑驱,在消費(fèi)者沒有向消息中間件服務(wù)器發(fā)送確認(rèn)之前竭恬,這個(gè)消息會(huì)被重復(fù)投遞跛蛋,確保消息的可靠性消費(fèi),而最大努力通知型則是沒有明說依靠消息隊(duì)列來通知消息痊硕,而是依靠的是支付寶這個(gè)系統(tǒng)赊级。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末岔绸,一起剝皮案震驚了整個(gè)濱河市盒揉,隨后出現(xiàn)的幾起案子羡洛,更是在濱河造成了極大的恐慌翘县,老刑警劉巖谴分,帶你破解...
    沈念sama閱讀 211,290評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異忘伞,居然都是意外死亡氓奈,警方通過查閱死者的電腦和手機(jī)舀奶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門罗岖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人桑包,你說我怎么就攤上這事∩沼保” “怎么了泳梆?”我有些...
    開封第一講書人閱讀 156,872評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵憎账,是天一觀的道長(zhǎng)胞皱。 經(jīng)常有香客問我,道長(zhǎng)策菜,這世上最難降的妖魔是什么酒贬? 我笑而不...
    開封第一講書人閱讀 56,415評(píng)論 1 283
  • 正文 為了忘掉前任躏将,我火速辦了婚禮辕翰,結(jié)果婚禮上喜命,老公的妹妹穿的比我還像新娘沟沙。我一直安慰自己河劝,他們只是感情好清焕,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評(píng)論 6 385
  • 文/花漫 我一把揭開白布橄唬。 她就那樣靜靜地躺著,像睡著了一般融柬。 火紅的嫁衣襯著肌膚如雪颊咬。 梳的紋絲不亂的頭發(fā)上务甥,一...
    開封第一講書人閱讀 49,784評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音喳篇,去河邊找鬼敞临。 笑死,一個(gè)胖子當(dāng)著我的面吹牛麸澜,可吹牛的內(nèi)容都是我干的挺尿。 我是一名探鬼主播,決...
    沈念sama閱讀 38,927評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼炊邦,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼编矾!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起馁害,我...
    開封第一講書人閱讀 37,691評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤窄俏,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后蜗细,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體裆操,經(jīng)...
    沈念sama閱讀 44,137評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評(píng)論 2 326
  • 正文 我和宋清朗相戀三年炉媒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了踪区。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,622評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡吊骤,死狀恐怖缎岗,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情白粉,我是刑警寧澤传泊,帶...
    沈念sama閱讀 34,289評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站鸭巴,受9級(jí)特大地震影響眷细,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鹃祖,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評(píng)論 3 312
  • 文/蒙蒙 一溪椎、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦校读、人聲如沸沼侣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蛾洛。三九已至,卻和暖如春雁芙,著一層夾襖步出監(jiān)牢的瞬間轧膘,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來泰國(guó)打工兔甘, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留扶供,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,316評(píng)論 2 360
  • 正文 我出身青樓裂明,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親太援。 傳聞我的和親對(duì)象是個(gè)殘疾皇子闽晦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評(píng)論 2 348

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