MQ系列1:消息中間件執行原理
MQ系列2:消息中間件的技術選型
MQ系列3:RocketMQ 架構分析
MQ系列4:NameServer 原理解析
MQ系列5:RocketMQ消息的發送模式
MQ系列6:消息的消費
MQ系列7:消息通信,追求極致性能
MQ系列8:數據存儲,消息隊列的高可用保障
MQ系列9:高可用架構分析
MQ系列10:如何保證消息冪等性消費
MQ系列11:如何保證消息可靠性傳輸
MQ系列12:如何保證消息順序性
1 背景
我們在前面兩個章節中,介紹了消息組件如何保證可靠性傳輸和順序行消費,參考上面系列的11、12章節。
- 比如在消息生產階段,如何保證消息發出的穩定性和可靠性;
- 在消息服務器處理階段,如何保證消息從生產到發送出去,經過網絡傳輸,再到達Broker服務器並被接收的這整個階段的可靠性,即如何使用ACK機制來保證消息傳遞的可靠性;
- 還有就是消息消費的可靠性,Broker作為消息服務器,消息接收並持久化消息並消費的整個過程的可靠性如何保障。
對於消息隊列組件來說,這幾個步驟出現問題,都有可能造成消息隊列無法進行正常運行,消息堆積的情況發生。
另外一種情況可能就是突發的流量峰值,這種一般發生在某種消費促銷活動或者各種搶購、競拍場景中。
2 原因分析
2.1 消息生產(Producer)遠超預期
消息的生產的規模遠超過原來的預期值,成數倍甚至幾十倍的增長,這種產生的原因可能如下:
- 比如遇到各種流量沖擊的活動:618、雙11大促、競拍、搶購、秒殺業務。(這種需要做好容量預估管理)
- 程序缺陷;死循環調用、批量請求、內存泄漏導致的流量飆升問題。(這種需要做好)

2.2 消息接收和持久化出現故障
Broker服務器接收消息並持久化出現問題:服務故障、網絡延遲、持久化失敗等,這種情況一般也比較少見...
2.3 消息消費(Consumer)能力下降致消息堆積
出現原因可能有如下幾種:
- 消費失敗時大量重試導致消息堆積。
- 消費者程序的故障:如 程序死鎖,io阻塞等。
- 消費者資源瓶頸:目前的主流消息隊列,單個節點消息收發的性能可以達到萬級別甚至10萬級+的水平。除非容量預估沒有做好,一般不會出現這種問題。即使出現這種問題,通過Scale Out Broker 的實例數也是比較輕松可以解決的。
3 消息堆積的解決方案
根據上面的整理,在遇到消息堆積的時候,先檢查下導致堆積的原因,看符合上述的三個原因的哪一個。
- 消息生產(Producer)遠超預期
- 消息接收和持久化出現故障
- 消息消費(Consumer)能力下降致消息堆積
找到原因之后,把問題處理完成,然后臨時擴容,來處理堆積的消息數據。具體操作步驟如下,參考下面的圖:
- 先分析原因,如果是Consumer或者Broker出現故障要先確保恢復故障;如果是消息消費問題,先修復程序問題。
- 暫停現有Consumer的消費動作。
- 臨時建立好原先10倍(或者N倍)的queue數量,即新建topic,partition分區是原來的10倍。
- 寫一個程序,這個程序只做簡單的轉發工作,目的就是將消費積壓的消息,均勻的消費到臨時擴容好的queue里(這里面有10倍的容量)。
- Consumer也擴容10倍,對應一個Consumer消費一個臨時的Queue。相應的被消費者依賴的業務處理服務也需要對應的擴容,包含緩存、數據庫、文件服務等等。
- 快速消費結束之后,記得恢復原來的消費架構,避免大量資源浪費。

總結
本文介紹了消息堆積可能導致的原因,以及基本的處理步驟。大部分消息中間件的健壯性都是非常好的。
業務的不合理使用和擴展一般是主要誘因,所以平時需要多關注業務服務的變化。
