前言
之前我們一起了解了使用RocketMQ事務(wù)消息解決生產(chǎn)者發(fā)送消息時(shí)消息丟失的問題,但使用了事務(wù)消息后消息就一定不會(huì)丟失了嗎丛晦,肯定是不能保證的褒纲。
因?yàn)殡m然我們解決了生產(chǎn)者發(fā)送消息時(shí)候的消息丟失問題,但也只是保證Broker正確的接收到了消息荐开,實(shí)際上接收到的消息會(huì)保存在os cache中模孩,如果此時(shí)broker機(jī)器突然宕機(jī)尖阔,os cache中的消息數(shù)據(jù)就丟失掉了。
而且就算是os cache中的消息已經(jīng)刷盤到了磁盤中榨咐,如果磁盤突然就壞了诺祸,消息是不是也就丟失了。
所以我們還要考慮Broker如何保證消息不丟失祭芦。
Broker的消息丟失解決方案
說到這里筷笨,我們就進(jìn)入主題了,首先解決臨時(shí)存在os cache,而未刷新到磁盤導(dǎo)致的消息丟失問題胃夏,那么如何解決呢轴或?
看過之前系列文章的小伙伴都知道,Broker是有兩種刷盤機(jī)制的仰禀,同步刷盤和異步刷盤照雁,詳細(xì)內(nèi)容可以回顧一下這篇文章:<u>深入研究Broker是如何持久化的</u>。
解決的方式就是把異步刷盤改為同步刷盤答恶,具體操作就是修改一下broker的配置文件饺蚊,將其中的flushDiskType配置設(shè)置為:SYNC_FLUSH,默認(rèn)它的值是ASYNC_FLUSH悬嗓,即異步刷盤污呼。
調(diào)整為同步刷盤后,只要MQ告訴我們消息發(fā)送成功了包竹,那么就說明消息已經(jīng)在磁盤中了燕酷。
接下來就要解決磁盤壞了導(dǎo)致的消息丟失問題了。
這個(gè)問題其實(shí)也很好解決周瞎,只要我們使用RockerMQ的高可用集群模式就可以了苗缩,也就是說如果返回消息發(fā)送成功的響應(yīng),那就代表Master Broker已經(jīng)把數(shù)據(jù)同步到了Slave Broker中声诸,保證數(shù)據(jù)有多個(gè)備份酱讶。
這樣一來就算是Master Broker突然宕機(jī) ,也可以通過Dledger技術(shù)進(jìn)行主從的自動(dòng)切換彼乌,使用我們備份的數(shù)據(jù)泻肯,這其中的原理我們已經(jīng)講過了,小伙伴們可以自己去復(fù)習(xí)回顧一下囤攀。<u>Dledger是如何實(shí)現(xiàn)主從自動(dòng)切換的</u>
Consumer的消息丟失解決方案
到這里软免,我們已經(jīng)確保了生產(chǎn)者和Broker的消息不會(huì)丟失了宫纬,那么消費(fèi)者處理消息的時(shí)候會(huì)不會(huì)導(dǎo)致消息丟失呢焚挠?
答案是肯定的。
比如說我們的積分系統(tǒng)拿到了消息漓骚,還未執(zhí)行該執(zhí)行的操作蝌衔,先返回給broker這條消息的offset,說這條消息已經(jīng)處理過了蝌蹂。然后突然宕機(jī)了噩斟,這就導(dǎo)致mq認(rèn)為這條消息已經(jīng)處理過了,而實(shí)際并沒有處理孤个,所以這條消息就丟失掉了剃允。
對(duì)于Kafka和RabbitMQ來講,默認(rèn)的消費(fèi)模式就是上邊這種自動(dòng)提交的模式,所以是有可能導(dǎo)致消息丟失掉的斥废。
而RocketMQ的消費(fèi)者有點(diǎn)不一樣椒楣,它本身就是需要手動(dòng)返回消息處理成功的響應(yīng)的。
所以其實(shí)Consumer的消息丟失解決方案也很簡單牡肉,就是將自動(dòng)提交改為手動(dòng)提交捧灰。
消息零丟失方案的優(yōu)缺點(diǎn)分析
如果在系統(tǒng)中落地一套消息零丟失的方案,無論什么場(chǎng)景都保證消息的可靠性统锤,這似乎聽起來不錯(cuò)毛俏,這也是它的優(yōu)點(diǎn)所在,保證系統(tǒng)的數(shù)據(jù)都是正確的饲窿,不會(huì)有丟失的情況煌寇。
但它有什么缺點(diǎn)呢?
首先免绿,引入了這套解決方案之后唧席,系統(tǒng)的復(fù)雜度變高了,想想事務(wù)消息的實(shí)現(xiàn)方式你肯定會(huì)這么覺得嘲驾。
而且比較嚴(yán)重的缺點(diǎn)是淌哟,它會(huì)導(dǎo)致系統(tǒng)的性能嚴(yán)重的下降,比如原來每秒可以處理好幾萬條的消息辽故,結(jié)果在引入消息零丟失這套方案之后徒仓,可能每秒就只能處理幾千條消息了。
其實(shí)只要隨便思考一下誊垢,就可以想明白這個(gè)問題掉弛。
事務(wù)消息的復(fù)雜性導(dǎo)致生產(chǎn)消息的過程耗時(shí)更久了,同步刷盤的策略導(dǎo)致寫入磁盤后才返回消息喂走,自然也會(huì)增加耗時(shí)殃饿,而消費(fèi)者如果異步的處理消息,直接返回成功芋肠,整個(gè)流程的速度會(huì)更快乎芳。
所以說引入這么一套消息零丟失的方案,對(duì)于性能的影響還是很大的帖池。
總結(jié)
其實(shí)關(guān)于消息零丟失的方案無外乎就這么多奈惑,所以本篇文章內(nèi)容不是很多。
既然我們剛才聊了消息零丟失方案的缺點(diǎn)睡汹,那么就繼續(xù)討論一下肴甸,究竟什么場(chǎng)景下需要引入這套方案吧。
王子給大家介紹一下自己的想法囚巴。
一般我們對(duì)于跟金錢原在、交易以及核心數(shù)據(jù)相關(guān)的系統(tǒng)和核心鏈路友扰,可以采用這套方案。
比如說我們文章中舉的例子:支付系統(tǒng)庶柿、訂單系統(tǒng)焕檬、積分系統(tǒng)。
而對(duì)于其他的沒那么核心的場(chǎng)景澳泵,丟失一些數(shù)據(jù)問題也不大实愚,就不應(yīng)該采用這套方案了,或者說可以做一些簡化兔辅,比如事務(wù)消息改成失敗重試幾次的機(jī)制腊敲,刷盤策略改為異步刷盤。
那么小伙伴們?cè)谄綍r(shí)的工作中维苔,這套方案是怎么應(yīng)用到生產(chǎn)環(huán)境中的呢碰辅?歡迎留言討論。
往期文章推薦:
深入研究RocketMQ生產(chǎn)者發(fā)送消息的底層原理