現象描述:
- 從全局看,隊列中的任務在正常的寫入和消費
- 查看 rabbitmq server 沒有發現任何錯誤日誌
- 磁盤佔用一直在增加,增加的路徑是 mnesia/rabbit@xxxx/msg_stores/vhosts/xxxx/msg_store_persistent 下面的路徑,都是一堆的 rdq 文件
- 把這些隊列佔用的磁盤空間全加起來,也沒有實際被佔用的磁盤空間多
為什麼會這樣?
這就要聊到 rabbitmq 的持久化機制和 rdq 文件的作用了
rdq 就是 rabbit disk queue。rdq 文件就是 rabbitmq 會把數據持久化在磁盤上,對應的具體文件就是 rdq 文件。
rabbitmq 同一個 vhost 下的所有隊列,都會寫入同一個 rdq 文件,而不是一個隊列一個 rdq 文件。當 rdq 文件大於 16MB 就會新創建一個 rdq 文件
所以 rdq 會有文件的編號
16.1 MiB [#### ] 508357.rdq
16.0 MiB [#### ] 508333.rdq
16.0 MiB [#### ] 508361.rdq
16.0 MiB [#### ] 508324.rdq
16.0 MiB [#### ] 508360.rdq
16.0 MiB [#### ] 508325.rdq
16.0 MiB [#### ] 508338.rdq
16.0 MiB [#### ] 508314.rdq
16.0 MiB [#### ] 508363.rdq
16.0 MiB [#### ] 508349.rdq
16.0 MiB [#### ] 508362.rdq
16.0 MiB [#### ] 508315.rdq
那麼 rdq 文件是怎麼刪除和釋放的?
消息確認(ACK)並且 沒有消費者需要 再讀時,該消息在內存和磁盤上都可以刪除。
由於文件是順序寫的,RabbitMQ 不會在文件中間打洞刪除消息,而是採用 整段回收:
如果一個 rdq 文件裏的所有消息都被確認消費了,那麼整個文件會被刪除(釋放磁盤空間)。
如果還有未消費的消息,文件保留。
所以刪除是 段級別,不是逐條消息的物理刪除。
所以,如果有一些消息一直沒有被消費的話,會導致 rdq 文件一直堆積導致磁盤被漲爆
這也解答了「把這些隊列佔用的磁盤空間全加起來,也沒有實際被佔用的磁盤空間多」發生的原因。有些隊列雖然數據很少,但是隻有有數據沒有消費掉,就會連累整個 rdq 文件無法釋放