面試題
如何解決消息隊列的延時以及過時失效問題?消息隊列滿了之後該怎麼處理?有幾百萬消息持續積壓幾小時,說說怎麼解決?mysql
面試題剖析
你看這問法,其實本質針對的場景,都是說,可能你的消費端出了問題,不消費了;或者消費的速度極其慢。接着就坑爹了,可能你的消息隊列集羣的磁盤都快寫滿了,都沒人消費,這個時候怎麼辦?或者是這整個就積壓了幾個小時,你這個時候怎麼辦?或者是你積壓的時間太長了,致使好比 RabbitMQ 設置了消息過時時間後就沒了怎麼辦?面試
因此就這事兒,其實線上挺常見的,通常不出,一出就是大 case。通常常見於,舉個例子,消費端每次消費以後要寫 mysql,結果 mysql 掛了,消費端 hang 那兒了,不動了;或者是消費端出了個什麼岔子,致使消費速度極其慢。
關於這個事兒,咱們一個一個來梳理吧,先假設一個場景,咱們如今消費端出故障了,而後大量消息在 mq 裏積壓,如今出事故了,慌了。sql
大量消息在 mq 裏積壓了幾個小時了還沒解決
幾千萬條數據在 MQ 裏積壓了七八個小時,從下午 4 點多,積壓到了晚上 11 點多。這個是咱們真實遇到過的一個場景,確實是線上故障了,這個時候要否則就是修復 consumer 的問題,讓它恢復消費速度,而後傻傻的等待幾個小時消費完畢。這個確定不能在面試的時候說吧。架構
一個消費者一秒是 1000 條,一秒 3 個消費者是 3000 條,一分鐘就是 18 萬條。因此若是你積壓了幾百萬到上千萬的數據,即便消費者恢復了,也須要大概 1 小時的時間才能恢復過來。.net
通常這個時候,只能臨時緊急擴容了,具體操做步驟和思路以下:blog
先修復 consumer 的問題,確保其恢復消費速度,而後將現有 consumer 都停掉。
新建一個 topic,partition 是原來的 10 倍,臨時創建好原先 10 倍的 queue 數量。
而後寫一個臨時的分發數據的 consumer 程序,這個程序部署上去消費積壓的數據,消費以後不作耗時的處理,直接均勻輪詢寫入臨時創建好的 10 倍數量的 queue。
接着臨時徵用 10 倍的機器來部署 consumer,每一批 consumer 消費一個臨時 queue 的數據。這種作法至關因而臨時將 queue 資源和 consumer 資源擴大 10 倍,以正常的 10 倍速度來消費數據。
等快速消費完積壓數據以後,得恢復原先部署的架構,從新用原先的 consumer 機器來消費消息。
mq 中的消息過時失效了
假設你用的是 RabbitMQ,RabbtiMQ 是能夠設置過時時間的,也就是 TTL。若是消息在 queue 中積壓超過必定的時間就會被 RabbitMQ 給清理掉,這個數據就沒了。那這就是第二個坑了。這就不是說數據會大量積壓在 mq 裏,而是大量的數據會直接搞丟。隊列
這個狀況下,就不是說要增長 consumer 消費積壓的消息,由於實際上沒啥積壓,而是丟了大量的消息。咱們能夠採起一個方案,就是批量重導,這個咱們以前線上也有相似的場景幹過。就是大量積壓的時候,咱們當時就直接丟棄數據了,而後等過了高峯期之後,好比你們一塊兒喝咖啡熬夜到晚上12點之後,用戶都睡覺了。這個時候咱們就開始寫程序,將丟失的那批數據,寫個臨時程序,一點一點的查出來,而後從新灌入 mq 裏面去,把白天丟的數據給他補回來。也只能是這樣了。資源
假設 1 萬個訂單積壓在 mq 裏面,沒有處理,其中 1000 個訂單都丟了,你只能手動寫程序把那 1000 個訂單給查出來,手動發到 mq 裏去再補一次。部署
mq 都快寫滿了
若是消息積壓在 mq 裏,你很長時間都沒有處理掉,此時致使 mq 都快寫滿了,咋辦?這個還有別的辦法嗎?沒有,誰讓你第一個方案執行的太慢了,你臨時寫程序,接入數據來消費,消費一個丟棄一個,都不要了,快速消費掉全部的消息。而後走第二個方案,到了晚上再補數據吧。
原文連接:https://blog.csdn.net/Iperishing/article/details/86676682消息隊列