1.客服反饋的一個(gè)奇怪問(wèn)題:支付之后沒(méi)有收到紅包
客服反饋用戶支付之后可以拿到一個(gè)現(xiàn)金紅包的,但是在支付成功之后翩剪,沒(méi)有收到乳怎。
按理來(lái)說(shuō),訂單系統(tǒng)在完成支付之后前弯,會(huì)推送一條消息到rocketMQ蚪缀,然后紅包系統(tǒng)會(huì)從RocketMQ接受那條消息去給用戶發(fā)現(xiàn)金紅包,我們看下圖
但是從訂單系統(tǒng)和紅包系統(tǒng)當(dāng)天那個(gè)時(shí)間段的日志來(lái)看恕出,居然只看到了訂單系統(tǒng)有推送消息到RocketMQ的日志询枚,但是并沒(méi)有看到紅包系統(tǒng)從RocketMQ中接收消息以及發(fā)現(xiàn)金紅包的日志。
于是推測(cè)浙巫,問(wèn)題可能就出在這兒了金蜀,是不是支付訂單消息在傳輸?shù)倪^(guò)程中丟失了?導(dǎo)致現(xiàn)金紅包沒(méi)有派發(fā)出去的畴!
那么接著我們就來(lái)一步一步分析一下渊抄,對(duì)于MQ的使用過(guò)程中,到底有哪些地方會(huì)導(dǎo)致消息丟失丧裁?
2护桦、訂單系統(tǒng)推送消息到MQ的過(guò)程會(huì)丟失消息嗎?
我們先看第一個(gè)問(wèn)題煎娇,訂單系統(tǒng)在接收到訂單支付成功的通知之后二庵,必然會(huì)去推送一條訂單支付成功的消息到MQ的,那么在這個(gè)過(guò)程中缓呛,會(huì)出現(xiàn)丟失消息的問(wèn)題嗎催享?
其實(shí)答案是顯而易的,有可能會(huì)丟失
舉一個(gè)比較常見(jiàn)的例子哟绊,比如訂單系統(tǒng)在推送消息到RocketMQ的過(guò)程中睡陪,是通過(guò)網(wǎng)絡(luò)去進(jìn)行傳輸?shù)模沁@個(gè)時(shí)候恰巧可能網(wǎng)絡(luò)發(fā)生了抖動(dòng)匿情,也就是網(wǎng)絡(luò)突然有點(diǎn)問(wèn)題,導(dǎo)致這次網(wǎng)絡(luò)通信失敗了信殊。
于是這個(gè)消息必然就沒(méi)有成功投遞給MQ
我們看下面的圖里的示意炬称,我用紅圈標(biāo)志出來(lái)了訂單系統(tǒng)投遞消息到MQ可能因?yàn)榫W(wǎng)絡(luò)問(wèn)題導(dǎo)致失敗的情況。
除此之外涡拘,大家覺(jué)得還有沒(méi)有其他的原因可能會(huì)導(dǎo)致訂單系統(tǒng)推送消息到MQ失敗的玲躯?
那是相當(dāng)?shù)亩嗔耍热鏜Q確實(shí)是收到消息了,但是他的網(wǎng)絡(luò)通信模塊的代碼出現(xiàn)了異常跷车,可能是他內(nèi)部的網(wǎng)絡(luò)通信的bug棘利,導(dǎo)致消息沒(méi)成功處理。
或者是你在寫消息到RocketMQ的過(guò)程中朽缴,剛好遇到了某個(gè)Leader Broker自身故障善玫,其他的Follower Broker正在嘗試切換為L(zhǎng)eader Broker,這個(gè)過(guò)程中也可能會(huì)有異常密强。類似的問(wèn)題可能還有其他的茅郎。
所以首先我們?cè)谑褂萌魏我粋€(gè)MQ的時(shí)候,無(wú)論是RocketMQ或渤,還是RabbitMQ系冗,或者是Kafka,大家都要明確一點(diǎn):不一定你發(fā)送消息出去就一定會(huì)成功薪鹦,有可能就會(huì)失敗掌敬,此時(shí)你的代碼里可能會(huì)拋出異常,也可能不會(huì)拋出異常池磁,這都不好說(shuō)奔害,具體要看到底什么原因?qū)е碌南⑼扑褪 ?/p>
3、消息到達(dá)MQ了框仔,MQ自己會(huì)導(dǎo)致消息丟失嗎舀武?
接著我們來(lái)看下一個(gè)問(wèn)題,即使我們的訂單系統(tǒng)成功的把消息寫入了MQ离斩,此時(shí)我們就可以想當(dāng)然的認(rèn)為你寫成功了银舱,消息就一定不會(huì)丟失了嗎?
這個(gè)也是未必的跛梗,我們來(lái)分析一下為什么
因?yàn)橥ㄟ^(guò)之前的RocketMQ的底層原理的分析寻馏,我們現(xiàn)在都明確了一點(diǎn),就是你的消息寫入MQ之后核偿,其實(shí)MQ可能僅僅是把這個(gè)消息給寫入到page cache里诚欠,也就是操作系統(tǒng)自己管理的一個(gè)緩沖區(qū),這本質(zhì)也是內(nèi)存漾岳。
大家注意圖里的示意轰绵,可能你認(rèn)為寫成功了一個(gè)消息,但是此時(shí)僅僅進(jìn)入了os cache尼荆,還沒(méi)寫入磁盤呢左腔。
然后這個(gè)時(shí)候,假如要是出現(xiàn)了Broker機(jī)器的崩潰捅儒,大家思考一下液样,機(jī)器一旦宕機(jī)振亮,是不是os cache內(nèi)存中的數(shù)據(jù)就沒(méi)了?
看到這里鞭莽,想必每個(gè)人都會(huì)倒吸一口氣坊秸,還真是,要是沒(méi)有研究過(guò)MQ底層原理的人澎怒,可能還真不知道數(shù)據(jù)要是進(jìn)入os cache的時(shí)候褒搔,碰上機(jī)器宕機(jī),內(nèi)存里的數(shù)據(jù)必然就會(huì)丟失了丹拯,你機(jī)器即使重啟了站超,然后重啟broker進(jìn)程,此時(shí)這個(gè)數(shù)據(jù)也沒(méi)了乖酬。
4死相、就算消息進(jìn)入磁盤了,你以為真的萬(wàn)無(wú)一失嗎咬像?
我們接著來(lái)看下一個(gè)問(wèn)題算撮,我們通過(guò)之前的學(xué)習(xí)也都知道一點(diǎn),那就是Broker把消息寫入os cache之后县昂,其實(shí)操作系統(tǒng)自己在一段不太確定的時(shí)間之后肮柜,他自己是會(huì)把數(shù)據(jù)從內(nèi)存刷入磁盤文件里去的
好,假設(shè)現(xiàn)在我們寫入MQ的一條消息已經(jīng)穩(wěn)穩(wěn)進(jìn)入Broker所在機(jī)器的磁盤文件里了倒彰,大家覺(jué)得這個(gè)時(shí)候數(shù)據(jù)一定不會(huì)丟失嗎审洞?
顯然不能想的那么簡(jiǎn)單,因?yàn)槿绻愕拇疟P出現(xiàn)故障待讳,比如磁盤壞了芒澜,你上面存儲(chǔ)的數(shù)據(jù)還是會(huì)丟失。
所以如果消息進(jìn)入了broker機(jī)器的磁盤之后创淡,萬(wàn)一你實(shí)在是點(diǎn)兒背痴晦,趕上機(jī)器剛好磁盤壞了,可能上面的消息也就都丟失了
我們看下圖琳彩,清晰的標(biāo)識(shí)出來(lái)誊酌,磁盤壞了也會(huì)導(dǎo)致上面存儲(chǔ)的數(shù)據(jù)丟失。
5露乏、即使紅包系統(tǒng)拿到了消息碧浊,就一定不會(huì)丟失了嗎?
好瘟仿,我們接著往后看辉词,即使紅包系統(tǒng)這個(gè)時(shí)候順利從MQ里拿到了一條消息,然后他就一定能安穩(wěn)的把現(xiàn)金紅包發(fā)出去嗎猾骡?
這也是未必的瑞躺。要解釋這個(gè)問(wèn)題,我們就要牽扯到消息的offset這個(gè)概念了兴想。
之前其實(shí)我們已經(jīng)給大家在底層原理分析的部分詳細(xì)解釋了MQ底層的存儲(chǔ)結(jié)構(gòu)幢哨,包括消息的offset的概念。
說(shuō)白了嫂便,offset就是代表了一個(gè)消息的標(biāo)識(shí)捞镰,代表了他的位置
我們給大家舉個(gè)例子,看下圖毙替,假設(shè)現(xiàn)在有兩個(gè)消息岸售,offset分別為1和2。
現(xiàn)在我們假設(shè)紅包系統(tǒng)已經(jīng)獲取到了消息1了厂画,然后消息1此時(shí)就在他的內(nèi)存里凸丸,正準(zhǔn)備運(yùn)行代碼去派發(fā)現(xiàn)金紅包呢,但是要注意袱院,此時(shí)還沒(méi)派發(fā)現(xiàn)金紅包屎慢。
我們都知道,默認(rèn)情況下忽洛,MQ的消費(fèi)者有可能會(huì)自動(dòng)提交已經(jīng)消費(fèi)的offset腻惠,那么如果此時(shí)你還沒(méi)處理這個(gè)消息派發(fā)紅包的情況下,MQ的消費(fèi)者可能直接自動(dòng)給你提交這個(gè)消息1的offset到broker去了欲虚,標(biāo)識(shí)為你已經(jīng)成功處理了這個(gè)消息集灌,我們看下圖。
接著恰巧在這個(gè)時(shí)候欣喧,我們的紅包系統(tǒng)突然重啟了初肉,或者是宕機(jī)了臼隔,或者是可能在派發(fā)紅包的時(shí)候更新數(shù)據(jù)庫(kù)失敗了,總之就是他突然故障了氨淌,紅包系統(tǒng)的機(jī)器重啟了一下删咱,然后此時(shí)內(nèi)存里的消息1必然就丟失了,而且紅包也沒(méi)發(fā)出去。
6、用戶支付之后紅包到底為什么沒(méi)發(fā)送出去呢?
我們學(xué)習(xí)了今天的文章就可以來(lái)解答這個(gè)問(wèn)題了,為什么用戶支付了,但是紅包沒(méi)發(fā)出去呢样刷?
其實(shí)原因有多種可能,比如訂單系統(tǒng)推送消息到MQ就失敗了,壓根兒就沒(méi)推送過(guò)去;
或者是消息確實(shí)推送到MQ了,但是結(jié)果MQ自己機(jī)器故障克饶,把消息搞丟了;
或者是紅包系統(tǒng)拿到了消息远豺,但是他把消息搞丟了惊来,結(jié)果紅包還沒(méi)來(lái)得及發(fā)继准。
如果真的在生產(chǎn)環(huán)境里要搞明白這個(gè)問(wèn)題,就必須要打更多的日志去一點(diǎn)點(diǎn)分析消息到底是在哪個(gè)環(huán)節(jié)丟失了?
如果訂單系統(tǒng)推送了消息,結(jié)果紅包系統(tǒng)連消息都沒(méi)收到,那可能消息根本就沒(méi)發(fā)到MQ去,或者M(jìn)Q自己搞丟了消息漱逸。
如果紅包系統(tǒng)收到了消息诀黍,結(jié)果紅包沒(méi)派發(fā),那么就是紅包系統(tǒng)搞丟了消息仗处。