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消費者是如何獲取消息的

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM