RocketMQ的消息是怎麼丟失的

 

前言

通過之前文章的閱讀,有關RocketMQ的底層原理相信小夥伴們已經有了一個比較清晰的認識。

那麼接下來王子想跟大家討論一個話題,如果我們的項目中引入了MQ,勢必要面對的一個問題,就是消息丟失問題,今天我們就來聊聊消息是怎麼丟失的。

現在假設我們的業務是這樣的,用戶通過訂單系統下了一個訂單,訂單系統完成支付後會發送消息給RocketMQ,然後積分系統會從RocketMQ中消費消息,去給用戶增加積分,如下圖:

 

 

但是突然有一天有用戶反映,支付訂單之後,自己的積分並沒有增長,這是爲什麼呢?

經過排查日誌,我們只發現了推送消息給MQ的日誌,而沒有發現積分系統消費這條消息的日誌,這就導致了積分系統並沒有給用戶發放積分。

也就是說,消息在傳輸過程中丟失了。

在系統的核心鏈路中,如果發生消息丟失的問題,可能會產生惡劣的後果,爲了解決此類問題,我們必須弄明白什麼時候會發生消息丟失。

 

訂單系統推送消息過程中會丟失消息嗎?

我們先來看一下整個流程的第一步,訂單系統在支付成功之後,一定會把支付成功的消息推送給MQ,那麼在這個推送的過程中,消息可能丟失嗎?

答案是肯定的,一定會存在消息丟失的情況

比較常見的情況就是網絡抖動,在推送消息這一過程中是通過網絡進行通信的,那麼這個時候如果恰巧網絡出現了故障,導致通信失敗了,那麼這個消息必然就不會成功的推送到MQ中。

那除了網絡抖動外,還有沒有其他的情況導致推送失敗呢?

其實情況有很多,比如MQ成功接收到了消息,但是MQ本身的網絡模塊的代碼出現了異常,可能是內部實現的bug,導致消息沒有成功處理。

或者當我們推送消息給一個MQ的主從集羣的時候,剛好遇到Leader節點出現故障,其他的Follower正在嘗試切換爲Leader,這個過程中也可能導致消息丟失。

類似的問題還有其他的。

所以我們首先要明確一點,無論我們使用任何MQ中間件的時候,你發送出的消息都不一定能成功,而失敗的時候有可能會在你的代碼裏發生異常,也有可能不會拋出異常,具體要看什麼情況導致的發送失敗。

 

MQ接收到消息後,自己會把消息弄丟嗎?

接下來假設我們訂單系統推送到MQ這一過程沒有任何問題,消息成功到達了MQ中,此時訂單系統會認爲消息寫入成功了,那麼這時候消息就一定不會丟失了嗎?

答案是否定的,這個時候也不能保證消息的不丟失,我們來分析一下。

通過之前文章的瞭解,相信大家都還記得,當消息寫入到MQ後,MQ會把消息先寫入到os cache,也就是操作系統的緩存區中,本質也是內存,如下圖:

 

也就是說,你認爲發送成功的消息,可能只存在於內存中,還沒到磁盤中。

那麼如果這個時候機器宕機了,os cache中的消息數據將會跟着丟失掉,是不是這個理。

 

那麼現在假設消息已經刷新到磁盤上了,是不是就可以保證萬無一失了呢?

顯然這個時候也是不能完全保證的,因爲雖然你把數據保存到了磁盤中,但是如果磁盤發生了故障,數據還是會丟失掉。

如果大家平時有了解一下新聞熱點,會聽說過某某互聯網公司,由於數據存儲在磁盤上沒有冗餘備份,結果磁盤發生故障導致好多年的核心數據全部丟失,大量工作都功虧一簣,這就是血淋淋的教訓。

 

積分系統消費到了消息就能保證消息的不丟失了嗎?

那麼到現在,經歷了重重困境,假設積分系統終於能夠消費到這條消息了,那麼它就能安穩的把積分正常的發放給用戶嗎?

答案依然是否定的。

看過之前文章的小夥伴們應該還記得消費者在進行消費時,是有一個offset的概念的。

這個offset說白了就是個進度標識,讓MQ知道消費者消費到了哪,下次好接着向下消費。

現在假設我們有兩條消息,offset爲1和2。

 

假設我們的積分系統接收到了消息1,那麼消息1就在積分系統的內存中,正要準備給用戶發放積分。

而默認情況下,消費者會自動提交已經消費的消息的offset,所以當積分系統獲取消息後,可能直接就把消息1的offset提交給了MQ,標識爲已經處理了這條消息。

那麼此時,如果積分系統突然宕機,還未發放積分給用戶,那麼這條消息1自然就丟失了,因爲MQ已經把他標記成了已處理,實際積分系統還未處理。

所以消費者獲得消息後也是可能發生消息丟失的。

 

總結

好了,看過今天的文章,相信小夥伴們對於RocketMQ的消息是怎麼丟失的會有一個更深刻的印象。

總結起來就是以下幾點:

1.生產者發送消息到MQ這一過程導致消息丟失

2.MQ自己發生故障導致消息丟失

3.消費者拿到消息後,由於操作不當導致消息丟失

所以任何的技術引入生產環境都是有風險的,引入前我們一定要做好功課。

今天的文章就說到這,小夥伴們可能會問王子,聊了這麼多,到底應該如何解決掉消息丟失的問題呢?

別急,我們下篇文章就會有解決方案了。

那麼小夥伴們針對MQ的消息丟失問題是怎麼解決的呢,歡迎大家留言和王子一起討論。

 

往期文章推薦:

什麼是消息中間件?主要作用是什麼?

常見的消息中間件有哪些?你們是怎麼進行技術選型的?

你懂RocketMQ 的架構原理嗎?

聊一聊RocketMQ的註冊中心NameServer

Broker的主從架構是怎麼實現的?

RocketMQ生產部署架構如何設計

RabbitMQ和Kafka的高可用集羣原理

RocketMQ的發送模式和消費模式

討論一下秒殺系統的技術難點與解決方案

秒殺系統中的扣減庫存和流量削峯

深入研究RocketMQ生產者發送消息的底層原理

深入研究Broker是如何持久化的

Dledger是如何實現主從自動切換的

深入研究RocketMQ消費者是如何獲取消息的

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章