消费消息删除_【进阶之路】可靠消息最终一致性解决方案
導(dǎo)言
大家好,我是南橘,從接觸java到現(xiàn)在也有差不多兩年時(shí)間了,兩年時(shí)間,從一名連java有幾種數(shù)據(jù)結(jié)構(gòu)都不懂超級(jí)小白,到現(xiàn)在懂了一點(diǎn)點(diǎn)的進(jìn)階小白,學(xué)到了不少的東西。知識(shí)越分享越值錢,我這段時(shí)間總結(jié)(包括從別的大佬那邊學(xué)習(xí),引用)了一些平常學(xué)習(xí)和面試中的重點(diǎn)(自我認(rèn)為),希望給大家?guī)硪恍椭?/p>
上一章,講了分布式系統(tǒng)中的柔性事務(wù)解決方案,并且介紹了一下2PC、3PC、與TCC解決方案。這一次,給大家介紹一種可靠消息最終一致性解決方案,用來實(shí)現(xiàn)分布式事務(wù)。
- 文章參考石杉的架構(gòu)筆記
1、可靠消息最終一致性事務(wù)
可靠消息最終一致性方案是指當(dāng)事務(wù)發(fā)起執(zhí)行完全本地事務(wù)后并發(fā)出一條消息,事務(wù)參與方(消息消費(fèi)者)一定能夠接收消息并處理事務(wù)成功,此方案強(qiáng)調(diào)的是只要消息發(fā)給事務(wù)參與方最終事務(wù)要達(dá)到一致。
2、實(shí)現(xiàn)可靠消息最終一致性方案
因?yàn)镽ocketMQ支持分布式消息,所以這個(gè)方案就用RocketMQ來實(shí)現(xiàn)。其實(shí)用什么消息中間件都只是業(yè)務(wù)上的選項(xiàng),重要的是原理。
應(yīng)某位同學(xué)的要求,我自己畫了一張圖。
- 生產(chǎn)者生產(chǎn)消息
- 消息確認(rèn)服務(wù)器確認(rèn)消息狀態(tài)
- RocketMQ傳遞消息
- 消費(fèi)者消費(fèi)消息
流程:
- 1、生產(chǎn)者發(fā)送消息給消息確認(rèn)服務(wù)器,消息確認(rèn)服務(wù)器存儲(chǔ)消息,并且把消息狀態(tài)改為待確認(rèn)。
- 2、生產(chǎn)者發(fā)送消息后執(zhí)行本地?cái)?shù)據(jù)庫(kù),執(zhí)行成功則確認(rèn)消息,失敗則刪除消息。
- 3、此時(shí)如果是確認(rèn)消息,那么消息確認(rèn)服務(wù)器就把數(shù)據(jù)庫(kù)里的消息狀態(tài)更新為“已發(fā)送”,同時(shí)將消息發(fā)送給MQ。
如果數(shù)據(jù)庫(kù)里更新消息的狀態(tài)失敗了,那么就拋異常退出了,就別投遞到MQ。
如果投遞MQ失敗報(bào)錯(cuò)了,那么就要拋異常讓本地?cái)?shù)據(jù)庫(kù)事務(wù)回滾。
這倆操作必須得一起成功,或者一起失敗。
- 4、消費(fèi)者一直等著從MQ消費(fèi)消息,如果消費(fèi)到了消息,那么就操作自己本地?cái)?shù)據(jù)庫(kù)
- 5、如果操作成功了,就反過來通知消息確認(rèn)服務(wù)器,說自己處理成功了,然后消息確認(rèn)服務(wù)器就會(huì)把消息的狀態(tài)設(shè)置為“已完成”。
流程是不是很簡(jiǎn)單?但是要保證消息的最終一致性和可靠性,還是有不少的工作要做的。
3、如何保證生產(chǎn)者服務(wù)對(duì)消息的可靠投遞
要保證生產(chǎn)者消息的可靠投遞,生產(chǎn)者需要將消息存入自己的數(shù)據(jù)庫(kù)中,根據(jù)據(jù)自己的執(zhí)行結(jié)果,調(diào)用可靠消息服務(wù)的接口。
如果本地?cái)?shù)據(jù)庫(kù)操作執(zhí)行成功了,那么就找可靠消息服務(wù)確認(rèn)那條消息。如果本地?cái)?shù)據(jù)庫(kù)操作失敗了,那么就找可靠消息服務(wù)刪除那條消息。
同時(shí),在消息確認(rèn)服務(wù)器里開發(fā)一個(gè)后臺(tái)定時(shí)運(yùn)行的線程,不停的輪詢檢查各個(gè)消息的狀態(tài)。
如果上游服務(wù)操作完本地?cái)?shù)據(jù)庫(kù)之后,通知可靠消息服務(wù)確認(rèn)消息或者刪除消息的時(shí)候,出現(xiàn)了問題。這種情況,消息服務(wù)器中的消息一直是“待確認(rèn)”狀態(tài),就認(rèn)為這個(gè)消息出了點(diǎn)什么問題,可以回調(diào)生產(chǎn)者提供的一個(gè)接口,確認(rèn)生產(chǎn)者數(shù)據(jù)庫(kù)操作狀態(tài)。
如果上游服務(wù)器執(zhí)行成功了,那么可靠消息服務(wù)將消息狀態(tài)修改為“已發(fā)送”,同時(shí)投遞消息到MQ。
如果上游服務(wù)執(zhí)行失敗,那么可靠消息服務(wù)將數(shù)據(jù)庫(kù)中的消息刪除即可。
通過這套機(jī)制,就可以保證,可靠消息服務(wù)一定會(huì)嘗試完成消息到MQ的投遞。
4、如何保證消費(fèi)者服務(wù)器對(duì)消息的可靠接收
要保消費(fèi)者消息的可靠接受,也需要在消息確認(rèn)服務(wù)器里開發(fā)一個(gè)后臺(tái)定時(shí)運(yùn)行的線程,通過這個(gè)線程,不停的輪詢檢查各個(gè)消息的狀態(tài)。
如果消息狀態(tài)一直是“已發(fā)送”的狀態(tài),始終沒有變成“已完成”,那么就說明消費(fèi)者服務(wù)始終沒有處理成功,這個(gè)時(shí)候消確認(rèn)服務(wù)器就可以再次嘗試重新投遞消息到MQ,讓消費(fèi)者服務(wù)再次處理。
當(dāng)然,為了保證數(shù)據(jù)的一致性,不至于出現(xiàn)重復(fù)消費(fèi)的情況,冪等性的實(shí)現(xiàn)是必不可少的。
5、保證消息傳遞機(jī)制的高可用性
一、RabbitMQ的高可用
我們之前的文章講過,RibbitMQ可以通過搭建集群來實(shí)現(xiàn)高可用,但是搭建不同的集群有不同的優(yōu)劣,這里就不再重復(fù)水字?jǐn)?shù)了。
【進(jìn)階之路】消息隊(duì)列——RabbitMQ原理(二)
二、RocketMQ的高可用
RocketMQ是一款出生在高并發(fā)分布式時(shí)代的消息中間件,所以他本身就是支持高并發(fā)和事務(wù)的。同時(shí),Name Server無狀態(tài),可線性擴(kuò)展,天然支持高可用。
- 1、多Master模式
多個(gè)Master節(jié)點(diǎn)組成的集群,即使有一個(gè)節(jié)點(diǎn)宕機(jī),對(duì)于整個(gè)集群來說也沒有什么影響。
缺點(diǎn):單個(gè)Master節(jié)點(diǎn)宕機(jī)期間, 未被消費(fèi)的消息在節(jié)點(diǎn)恢復(fù)之前不可用, 消息的實(shí)時(shí)性就收到影響。當(dāng)然,使用同步技術(shù)可以讓消息在各個(gè)節(jié)點(diǎn)之間同步,只是會(huì)導(dǎo)致效能和空間利用大幅下降,
- 2、多Master多Slave異步復(fù)制模式
在多Master的基礎(chǔ)上, 每個(gè)節(jié)點(diǎn)都有至少一個(gè)的Slave,Master節(jié)點(diǎn)可讀可寫,但是Slave節(jié)點(diǎn)只讀不寫, 這種情況似于MySQL的主備模式。
優(yōu)點(diǎn):單個(gè)Master節(jié)點(diǎn)宕機(jī)期間, Slave節(jié)點(diǎn)依舊可以讀取消息。
缺點(diǎn):異步復(fù)制的同步方式有可能導(dǎo)致消息丟失。
- 3、多Master多Slave同步雙寫模式
與多Master多Slave異步復(fù)制模式類似, 區(qū)別在于Master和Slave之間的數(shù)據(jù)通過同步的方式傳輸。
優(yōu)點(diǎn): 數(shù)據(jù)與服務(wù)都無單點(diǎn),Master宕機(jī)情況下,消息無延遲,服務(wù)可用性與數(shù)據(jù)可用性都非常高。
缺點(diǎn): 性能比異步復(fù)制模式稍低,大約低10%左右,發(fā)送單個(gè)消息的RT會(huì)稍高,目前主宕機(jī)后,備機(jī)不能自動(dòng)切換為主機(jī),后續(xù)會(huì)支持自動(dòng)切換功能。
三、Kafka 的高可用性
kafka本身是由多個(gè)broker組成,每個(gè)broker就是一個(gè)節(jié)點(diǎn);創(chuàng)建一個(gè)topic,這個(gè)topic可以劃分為多個(gè)partition,每個(gè)partition可以存在于不同的broker上,每個(gè)partition存放放一部分?jǐn)?shù)據(jù)。
所以kafka就是一個(gè)分布式消息隊(duì)列,一個(gè)topic的數(shù)據(jù),是分散放在多個(gè)機(jī)器上的,每個(gè)機(jī)器就放一部分?jǐn)?shù)據(jù)。
(找張圖片來展示一下)
kafka 0.8以后,提供了HA機(jī)制,就是replica副本機(jī)制。kafka會(huì)均勻的將一個(gè)partition的所有replica分布在不同的機(jī)器上,提高容錯(cuò)性。若某個(gè)broker宕機(jī)了,剛好其上有某個(gè)partition的leader,那么此時(shí)kafka會(huì)自動(dòng)重新選舉出一個(gè)新leader,繼續(xù)讀寫那個(gè)新leader即可。
寫數(shù)據(jù)的時(shí)候:生產(chǎn)者就是leader,將數(shù)據(jù)落地寫入本地磁盤,接著其他follower主動(dòng)從leader來拉數(shù)據(jù)。一旦所有follower同步好數(shù)據(jù),會(huì)發(fā)送ack給leader,leader收到所有follower的ack后,會(huì)返回寫成功的消息給生產(chǎn)者。
消費(fèi)的時(shí)候:只會(huì)從leader讀,但是只有一個(gè)消息已經(jīng)被所有follower都同步成功返回ack的時(shí)候,這個(gè)消息才會(huì)被讀到,即leader和所有follower上都有了這個(gè)消息。
結(jié)語(yǔ)
這篇文章基本上就是對(duì)于分布式事務(wù)的一次總結(jié)了。我覺得如果大家想更加深入的了解,可以和我一樣畫畫架構(gòu)圖,然后嘗試著自己搭建一個(gè)簡(jiǎn)單的服務(wù)。這樣效果真的不錯(cuò),雖然在實(shí)際工作中大部分公司已經(jīng)搭建了自己的框架,不過總是要不斷更新的~總有一天我們也會(huì)獨(dú)當(dāng)一面不是?
同時(shí)需要思維導(dǎo)圖的話,可以聯(lián)系我,畢竟知識(shí)越分享越香!
總結(jié)
以上是生活随笔為你收集整理的消费消息删除_【进阶之路】可靠消息最终一致性解决方案的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 批量打印pdf并合并_CAD批量打印攻略
- 下一篇: c语言两个for语句并列执行_C语言两个