rocketmq怎么保证数据不会重复_rocketmq如何保证消息不丢失
一、大體可以從三方面來說:
分別從Producer發送機制、Broker的持久化機制,以及消費者的offSet機制來最大程度保證消息不易丟失
從Producer的視角來看:如果消息未能正確的存儲在MQ中,或者消費者未能正確的消費到這條消息,都是消息丟失。
從Broker的視角來看:如果消息已經存在Broker里面了,如何保證不會丟失呢(宕機、磁盤崩潰)
從Consumer的視角來看:如果消息已經完成持久化了,但是Consumer取了,但是未消費成功且沒有反饋,就是消息丟失
從Producer分析:如何確保消息正確的發送到了Broker?
默認情況下,可以通過同步的方式阻塞式的發送,check SendStatus,狀態是OK,表示消息一定成功的投遞到了Broker,狀態超時或者失敗,則會觸發默認的2次重試。此方法的發送結果,可能Broker存儲成功了,也可能沒成功
采取事務消息的投遞方式,并不能保證消息100%投遞成功到了Broker,但是如果消息發送Ack失敗的話,此消息會存儲在CommitLog當中,但是對ConsumerQueue是不可見的。可以在日志中查看到這條異常的消息,嚴格意義上來講,也并沒有完全丟失
RocketMQ支持 日志的索引,如果一條消息發送之后超時,也可以通過查詢日志的API,來check是否在Broker存儲成功
從Broker分析:如果確保接收到的消息不會丟失?
消息支持持久化到Commitlog里面,即使宕機后重啟,未消費的消息也是可以加載出來的
Broker自身支持同步刷盤、異步刷盤的策略,可以保證接收到的消息一定存儲在本地的內存中
Broker集群支持 1主N從的策略,支持同步復制和異步復制的方式,同步復制可以保證即使Master 磁盤崩潰,消息仍然不會丟失
從Cunmser分析:如何確保拉取到的消息被成功消費?
消費者可以根據自身的策略批量Pull消息
Consumer自身維護一個持久化的offset(對應MessageQueue里面的min offset),標記已經成功消費或者已經成功發回到broker的消息下標
如果Consumer消費失敗,那么它會把這個消息發回給Broker,發回成功后,再更新自己的offset
如果Consumer消費失敗,發回給broker時,broker掛掉了,那么Consumer會定時重試這個操作
如果Consumer和broker一起掛了,消息也不會丟失,因為consumer 里面的offset是定時持久化的,重啟之后,繼續拉取offset之前的消息到本地
二、消息重復
上面在解決消息順序問題時,引入了一個新的問題,就是消息重復。那么RocketMQ是怎樣解決消息重復的問題呢?還是“恰好”不解決。
造成消息的重復的根本原因是:網絡不可達。只要通過網絡交換數據,就無法避免這個問題。所以解決這個問題的辦法就是不解決,轉而繞過這個問題。那么問題就變成了:如果消費端收到兩條一樣的消息,應該怎樣處理?
1、消費端處理消息的業務邏輯保持冪等性
2、保證每條消息都有唯一編號且保證消息處理成功與去重表的日志同時出現
第1條很好理解,只要保持冪等性,不管來多少條重復消息,最后處理的結果都一樣。第2條原理就是利用一張日志表來記錄已經處理成功的消息的ID,如果新到的消息ID已經在日志表中,那么就不再處理這條消息。
我們可以看到第1條的解決方式,很明顯應該在消費端實現,不屬于消息系統要實現的功能。第2條可以消息系統實現,也可以業務端實現。正常情況下出現重復消息的概率不一定大,且由消息系統實現的話,肯定會對消息系統的吞吐量和高可用有影響,所以最好還是由業務端自己處理消息重復的問題,這也是RocketMQ不解決消息重復的問題的原因。
RocketMQ不保證消息不重復,如果你的業務需要保證嚴格的不重復消息,需要你自己在業務端去重。
總結
以上是生活随笔為你收集整理的rocketmq怎么保证数据不会重复_rocketmq如何保证消息不丢失的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 拼多多怎么开启免密支付
- 下一篇: BBU+RRU基本介绍