開發與維運

淺談專有云MQ存儲空間的清理機制

image.png

在近⼀年的項⽬保障過程中,對專有云MQ產品的存儲⽔位清理模式⼀直存疑,總想一探究竟但又苦於工作繁忙、精力有限,直到最近⼀次項⽬保障過程中再次出現了類似的問題,⼤家對MQ Broker的⽔位清理機制仍然⽐較模糊,於是便有了這篇⽂章。希望能通過這篇⽂章將MQ Broker的消息清理機制講清楚。
⾸先,我們先來看⼀張MQ的消息保存時間和Broker磁盤存儲空間的⽔位趨勢圖(該圖來源於銅雀,⽬前已更名為SRE技術保障平臺)。通過該趨勢圖,可以看到紅線左側的消息保存時間(上⽅藍⾊趨勢線)和Broker磁盤存儲空間(下⽅綠⾊區域)呈現出規律性的波動。⽽紅線右側部分,隨著消息量的快速增加(通過Broker磁盤存儲空間快速上漲得出),開始⼀段時間消息保存時間還呈規律性波動,但接近最右側時,可以看到消息保存時間的波動頻率加快了,⽽且消息保存時間快速下降。那麼MQ對消息的清理機制到底是什麼呢?

image.png
圖1:消息保存時間&磁盤空間佔比趨勢圖

在介紹清理機制前,先來複習⼀下MQ的消息是如何進⾏存儲的。

image.png
圖2:commitlog

Producer發送的所有消息都存放在Broker節點的 /home/admin/store/commitlog ⽬錄下(專有云場景),每個commitlog的⼤⼩固定為1G。隨著時間的推移,當Broker接收的消息量越來越多時,就會在該⽬錄下⽣成多個⼤⼩為1G的commitlog⽂件。
ps: 特別聲明,雖然該⽬錄叫commitlog,但⽬錄中存儲的⽂件並不是程序⽇志,⽽是MQ Broker⽤來存儲消息的⽂件載體,在MQ產品中這種⽂件載體叫做commitlog。之所以這⾥做特別說明,是因為歷史上出現過由於誤認為此⽬錄下存儲的是程序⽇志,為了釋放磁盤存儲空間將⽬錄下的commitlog刪除導致MQ消息丟失的故障。這是⾎的教訓!這個⽬錄下的⽂件不要碰,不要碰,不要碰。
commitlog⽬錄下的⽂件讓MQ⾃行維護清理便可。那MQ⾃身是根據什麼規則來進⾏清理的呢?先來看⼀下MQ⾥⾯⼏個⽐較關鍵的閾值:

  • 72⼩時,MQ默認的消息保存時間。從圖1可以看出每次消息保存時間波動下降時,均會逼近到該值。
  • 凌晨4點,MQ默認的消息清理觸發時間。從圖1可以看出每次消息保存時間下降均在凌晨4點發生。
  • 75%,MQ默認的開始觸發清理磁盤存儲空間的閾值。
  • 85%,MQ內置的開始強制清理磁盤存儲空間的閾值。
  • 90%,MQ內置的Broker開始禁寫的磁盤存儲空間的閾值。

MQ會在兩個時機對commitlog進⾏清理,⼀是前文提到的每天凌晨4點;另⼀個是消息寫⼊時。通過以下表格可以更加清楚的看出具體的清理策略。

image.png

清理模式

  • 普通清理,這種清理模式只將72⼩時之前的commitlog清理掉,MQ在保證存儲72⼩時消息的前提下,儘量降低磁盤空間使⽤率。
  • 強制清理,這種清理模式只在Broker存儲空間⾼於85%的情況下觸發,此時MQ在對commitlog進⾏清理時,將不再考慮72⼩時的消息保留時間,⽽是要儘可能保證能夠接收新的MQ消息進來,因此會強制對 commitlog進⾏清理(因為如果不清理,磁盤空間使⽤率進⼀步上漲到90%後,Broker便會⾃動禁寫,新的消息便⽆法寫入)。當然也不會⼀次性將所有的commitlog清理掉,⽽是隻批量清理⼀部分(代碼中設置⼀個broker⼀次最多清理10個commitlog⽂件)。

我們回過頭來再看⼀下這個趨勢圖。

image.png
圖3:消息保存時間&磁盤空間佔比趨勢圖

  • 圖中1,2,3,4,5,6 處,Broker的存儲空間均未超過75%,在每⽇凌晨4點觸發了定時清理,將72⼩時之前的消息清理掉。可以看到在清理完成後,消息的保存時間都回落到了72⼩時左右。
  • 圖中7處,Broker的存儲空間使⽤率第⼀次達到了75%,但低於85%,觸發了消息寫⼊時的普通清理,此時清理的還是72⼩時之前的消息,可以看到消息保存時間在清理完成後回落到72⼩時左右,但存儲空間使⽤率下降的⾮常⼩,說明⽬前Broker中存儲的消息⼤部分都是72⼩時以內產⽣的。
  • 圖中8處,隨著消息的發送(消息寫⼊速度⽐較快),存儲空間使⽤率第⼆次達到了75%,仍低於85%,此時普通清理仍然是清理72⼩時之前的消息數據,可以看到磁盤空間使⽤率並沒有明顯下降。說明此時消息的寫⼊速度已經⾼於commitlog的清理速度。
  • 8之後發⽣的事情,由於此時消息寫⼊速度⾼於commitlog清理速度,雖然消息寫⼊時會觸發清理動作,但此時Broker中的消息都是72⼩時以內發送的,沒有清理掉任何commitlog,磁盤⽔位並沒有降低。隨著消息的不斷寫⼊,Broker的存儲⽔位不斷升⾼,消息的保存時間基本維持不變。
  • 8之後的之後,當Broker的存儲⽔位達到85%,此時Broker為了後續還能繼續提供服務,會開啟強制清理,此時MQ不再考慮72⼩時的消息保留時間,⽽是優先保證後續消息的順利寫⼊,於是會將72⼩時以內的消息也進⾏清理。整體表現為Broker的存儲⽔位達到85%時,基本不會上漲(只有在消息寫⼊量特別⼤時,消息寫⼊速度遠遠⼤於commitlog清理速度,才會繼續上漲),但由於清理了72⼩時以內的消息,會使Broker的消息保存時間開始降低,開始低於72⼩時,並隨著後續清理動作不斷降低。

    如上所述,消息寫⼊量特別⼤,消息寫⼊速度遠⾼於commitlog的清理速度,Broker的存儲⽔位在達到85%後還會繼續升⾼,直至達到90%時,Broker為了保護⾃身服務可⽤性,會⾃動開啟禁寫,此時發送到該Broker的消息會被拒絕掉。Broker的存儲⽔位不會進⼀步上升,⽽且此時Broker會開啟強制清理,對72⼩時以內的消息進⾏清理,以便使Broker的存儲⽔位降到90%以下,使Broker可以重新對外提供服務。

ps:實際在MQ的代碼實現層⾯,為了保證消息寫⼊Broker的性能,並不是每次寫⼊消息時都進⾏存儲
空間檢查和commitlog清理,⽽是通過定時任務來執⾏(該定時任務每10s執⾏⼀次)。

上述介紹的⼏個清理閾值中,有些是可調的,有些是內置在代碼中不可調的。⽐如“凌晨4點”,“72⼩時”,“75%”,這3個參數是⽤戶可以調整的MQ配置,“85%”,“90%”是寫死在代碼中的,是⽆法調整的。
查看Broker配置信息的⽅式如下,在Broker的docker中執⾏

sh /home/admin/rmq/bin/mqadmin getBrokerConfig -b ${IP}:10911
  • deleteWhen,對應“凌晨4點”
  • fileReservedTime,對應“72⼩時”
  • diskMaxUsedSpaceRatio,對應“75%”

在調整配置時,deleteWhen通常選在客戶MQ業務的低峰期進⾏,儘量避免commitlog清理對⽣產業務的影響。當Broker存儲⽔位出現快速上漲時,為避免存儲⽔位達到90%,出現禁寫影響⽣產業務的情況,需要同時調整fileReservedTime和diskMaxUsedSpaceRatio的默認設置,通過調整這兩個參數共同作⽤保證Broker的存儲空間可以及時得到清理(還有⼀種降⽔位的⽅式——關閉MQ消息軌跡)。當然這所有參數的調整都需要經過與產研的溝通與確認。

以上就是對MQ Broker消息清理機制的剖析,希望通過這篇⽂章能夠讓大家理解並掌握其清理機制,能夠處理實際工作中遇到的MQ Broker存儲⽔位快速上漲的問題。

我們是阿里雲智能全球技術服務-SRE團隊,我們致力成為一個以技術為基礎、面向服務、保障業務系統高可用的工程師團隊;提供專業、體系化的SRE服務,幫助廣大客戶更好地使用雲、基於雲構建更加穩定可靠的業務系統,提升業務穩定性。我們期望能夠分享更多幫助企業客戶上雲、用好雲,讓客戶雲上業務運行更加穩定可靠的技術,您可用釘釘掃描下方二維碼,加入阿里雲SRE技術學院釘釘圈子,和更多雲上人交流關於雲平臺的那些事。

image.png

Leave a Reply

Your email address will not be published. Required fields are marked *