如何解決消息隊(duì)列的延時(shí)以及過期失效問題?消息隊(duì)列滿了以后該怎么處理?有幾百萬消息持續(xù)積壓幾小 時(shí),說說怎么解決?

面試官心理分析

你看這問法,其實(shí)本質(zhì)針對的場景,都是說,可能你的消費(fèi)端出了問題,不消費(fèi)了;或者消費(fèi)的速度極其慢。接著就坑爹了,可能你的消息隊(duì)列集群的磁盤都快寫滿了,都沒人消費(fèi),這個(gè)時(shí)候怎么辦?或者是這整個(gè)就積壓了幾個(gè)小時(shí),你這個(gè)時(shí)候怎么辦?或者是你積壓的時(shí)間太長了,導(dǎo)致比如 RabbitMQ 設(shè)置了消息過期時(shí)間后就沒了怎么辦?

所以就這事兒,其實(shí)線上挺常見的,一般不出,一出就是大 case。一般常見于,舉個(gè)例子,消費(fèi)端每次消費(fèi)之后要寫 mysql,結(jié)果 mysql 掛了,消費(fèi)端 hang 那兒了,不動(dòng)了;或者是消費(fèi)端出了個(gè)什么岔子,導(dǎo)致消費(fèi)速度極其慢。


面試題剖析

關(guān)于這個(gè)事兒,我們一個(gè)一個(gè)來梳理吧,先假設(shè)一個(gè)場景,我們現(xiàn)在消費(fèi)端出故障了,然后大量消息在 mq里積壓,現(xiàn)在出事故了,慌了。

大量消息在 mq 里積壓了幾個(gè)小時(shí)了還沒解決

幾千萬條數(shù)據(jù)在 MQ 里積壓了七八個(gè)小時(shí),從下午 4 點(diǎn)多,積壓到了晚上 11 點(diǎn)多。這個(gè)是我們真實(shí)遇到過的一個(gè)場景,確實(shí)是線上故障了,這個(gè)時(shí)候要不然就是修復(fù) consumer 的問題,讓它恢復(fù)消費(fèi)速度,然后傻傻的等待幾個(gè)小時(shí)消費(fèi)完畢。這個(gè)肯定不能在面試的時(shí)候說吧。

一個(gè)消費(fèi)者一秒是 1000 條,一秒 3 個(gè)消費(fèi)者是 3000 條,一分鐘就是 18 萬條。所以如果你積壓了幾百萬到上千萬的數(shù)據(jù),即使消費(fèi)者恢復(fù)了,也需要大概 1 小時(shí)的時(shí)間才能恢復(fù)過來。

一般這個(gè)時(shí)候,只能臨時(shí)緊急擴(kuò)容了,具體操作步驟和思路如下:

????????????先修復(fù) consumer 的問題,確保其恢復(fù)消費(fèi)速度,然后將現(xiàn)有 consumer 都停掉。新建一個(gè) topic,partition 是原來的 10 倍,臨時(shí)建立好原先 10 倍的 queue 數(shù)量。然后寫一個(gè)臨時(shí)的分發(fā)數(shù)據(jù)的 consumer 程序,這個(gè)程序部署上去消費(fèi)積壓的數(shù)據(jù),消費(fèi)之后不做耗時(shí)的處理,直接均勻輪詢寫入臨時(shí)建立好的 10 倍數(shù)量的 queue。

????????????接著臨時(shí)征用 10 倍的機(jī)器來部署 consumer,每一批 consumer 消費(fèi)一個(gè)臨時(shí) queue 的數(shù)據(jù)。這種做法相當(dāng)于是臨時(shí)將 queue 資源和 consumer 資源擴(kuò)大 10 倍,以正常的 10 倍速度來消費(fèi)數(shù)據(jù)。

????????????等快速消費(fèi)完積壓數(shù)據(jù)之后,得恢復(fù)原先部署的架構(gòu),重新用原先的 consumer 機(jī)器來消費(fèi)消息。

mq 中的消息過期失效了

假設(shè)你用的是 RabbitMQ,RabbtiMQ 是可以設(shè)置過期時(shí)間的,也就是 TTL。如果消息在 queue 中積壓超過一定的時(shí)間就會(huì)被 RabbitMQ 給清理掉,這個(gè)數(shù)據(jù)就沒了。那這就是第二個(gè)坑了。這就不是說數(shù)據(jù)會(huì)大量積壓在 mq 里,而是大量的數(shù)據(jù)會(huì)直接搞丟。

這個(gè)情況下,就不是說要增加 consumer 消費(fèi)積壓的消息,因?yàn)閷?shí)際上沒啥積壓,而是丟了大量的消息。我們可以采取一個(gè)方案,就是批量重導(dǎo),這個(gè)我們之前線上也有類似的場景干過。就是大量積壓的時(shí)候,我們當(dāng)時(shí)就直接丟棄數(shù)據(jù)了,然后等過了高峰期以后,比如大家一起喝咖啡熬夜到晚上 12 點(diǎn)以后,用戶都睡覺了。這個(gè)時(shí)候我們就開始寫程序,將丟失的那批數(shù)據(jù),寫個(gè)臨時(shí)程序,一點(diǎn)一點(diǎn)的查出來,然后重新灌入 mq 里面去,把白天丟的數(shù)據(jù)給他補(bǔ)回來。也只能是這樣了。

假設(shè) 1 萬個(gè)訂單積壓在 mq 里面,沒有處理,其中 1000 個(gè)訂單都丟了,你只能手動(dòng)寫程序把那 1000 個(gè)訂單給查出來,手動(dòng)發(fā)到 mq 里去再補(bǔ)一次。

mq 都快寫滿了

如果消息積壓在 mq 里,你很長時(shí)間都沒有處理掉,此時(shí)導(dǎo)致 mq 都快寫滿了,咋辦?這個(gè)還有別的辦法嗎?沒有,誰讓你第一個(gè)方案執(zhí)行的太慢了,你臨時(shí)寫程序,接入數(shù)據(jù)來消費(fèi),消費(fèi)一個(gè)丟棄一個(gè),都不要了,快速消費(fèi)掉所有的消息。然后走第二個(gè)方案,到了晚上再補(bǔ)數(shù)據(jù)吧。


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容