RocketMq怎么保證消息不丟失


Producer發送消息階段
發送消息階段涉及到Producer到broker的網絡通信,因此丟失消息的幾率一定會有,那RocketMQ在此階段用了哪些手段保證消息不丟失了(或者說降低丟失的可能性)。

手段一:提供SYNC的發送消息方式,等待broker處理結果。RocketMQ提供了3種發送消息方式,分別是:

同步發送:Producer 向 broker 發送消息,阻塞當前線程等待 broker 響應 發送結果。
異步發送:Producer 首先構建一個向 broker 發送消息的任務,把該任務提交給線程池,等執行完該任務時,回調用戶自定義的回調函數,執行處理結果。
Oneway發送:Oneway 方式只負責發送請求,不等待應答,Producer只負責把請求發出去,而不處理響應結果。
我們在調用producer.send方法時,不指定回調方法,則默認采用同步發送消息的方式,這也是丟失幾率最小的一種發送方式。

手段二:發送消息如果失敗或者超時,則重新發送。

發送重試源碼如下,本質其實就是一個for循環,當發送消息發生異常的時候重新循環發送。默認重試3次,重試次數可以通過producer指定。
手段三:broker提供多master模式,即使某台broker宕機了,保證消息可以投遞到另外一台正常的broker上。

如果broker只有一個節點,則broker宕機了,即使producer有重試機制,也沒用,因此利用多主模式,當某台broker宕機了,換一台broker進行投遞。
總結

producer消息發送方式雖然有3種,但為了減小丟失消息的可能性盡量采用同步的發送方式,同步等待發送結果,利用同步發送+重試機制+多個master節點,盡可能減小消息丟失的可能性。
Broker處理消息階段
手段四:提供同步刷盤的策略

public enum FlushDiskType { SYNC_FLUSH, //同步刷盤 ASYNC_FLUSH//異步刷盤(默認) }

我們知道,當消息投遞到broker之后,會先存到page cache,然后根據broker設置的刷盤策略是否立即刷盤,也就是如果刷盤策略為異步,broker並不會等待消息落盤就會返回producer成功,也就是說當broker所在的服務器突然宕機,則會丟失部分頁的消息。

手段五:提供主從模式,同時主從支持同步雙寫

即使broker設置了同步刷盤,如果主broker磁盤損壞,也是會導致消息丟失。 因此可以給broker指定slave,同時設置master為SYNC_MASTER,然后將slave設置為同步刷盤策略。

此模式下,producer每發送一條消息,都會等消息投遞到master和slave都落盤成功了,broker才會當作消息投遞成功,保證休息不丟失。

總結

在broker端,消息丟失的可能性主要在於刷盤策略和同步機制。
RocketMQ默認broker的刷盤策略為異步刷盤,如果有主從,同步策略也默認的是異步同步,這樣子可以提高broker處理消息的效率,但是會有丟失的可能性。因此可以通過同步刷盤策略+同步slave策略+主從的方式解決丟失消息的可能。

Consumer消費消息階段
手段六:consumer默認提供的是At least Once機制

從producer投遞消息到broker,即使前面這些過程保證了消息正常持久化,但如果consumer消費消息沒有消費到也不能理解為消息絕對的可靠。因此RockerMQ默認提供了At least Once機制保證消息可靠消費。

何為At least Once?

Consumer先pull 消息到本地,消費完成后,才向服務器返回ack。

通常消費消息的ack機制一般分為兩種思路:

1、先提交后消費;

2、先消費,消費成功后再提交;

思路一可以解決重復消費的問題但是會丟失消息,因此Rocketmq默認實現的是思路二,由各自consumer業務方保證冪等來解決重復消費問題。

說白了,同步發送,同步落盤


免責聲明!

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



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