討論可靠性傳輸這個問題,我們需要從三個角度來分析:生產者弄丟數據、RocketMQ弄丟數據、消費者弄丟數據。
消費端弄丟了數據
對於消費端,如果我們在使用 Push 模式的情況下,只有我們消費返回成功,才會異步定期更新消費進度到 Broker 上。
如果消費端異常崩潰,可能導致消費進度未更新到 Broker 上,那么無非是 Consumer 可能重復拉取到已經消費過的消息。關於這個,就需要消費端做好消費的冪等性。
Broker 弄丟了數據?
我們首先來看看Broker的刷盤和復制方式。
刷盤
(1) 同步刷盤:如上圖所示,只有在消息真正持久化至磁盤后RocketMQ的Broker端才會真正返回給Producer端一個成功的ACK響應。同步刷盤對MQ消息可靠性來說是一種不錯的保障,但是性能上會有較大影響,一般適用於金融業務應用該模式較多。
(2) 異步刷盤:能夠充分利用OS的PageCache的優勢,只要消息寫入PageCache即可將成功的ACK返回給Producer端。消息刷盤采用后台異步線程提交的方式進行,降低了讀寫延遲,提高了MQ的性能和吞吐量。
一般地,異步刷盤只有在 Broker 意外宕機的時候會丟失部分數據,你可以設置 Broker 的參數 FlushDiskType 來調整你的刷盤策略(ASYNC_FLUSH 或者 SYNC_FLUSH)。
同步復制和異步復制
如果一個broker組有Master和Slave,消息需要從Master復制到Slave上,有同步和異步兩種復制方式。
同步復制: 也叫 “同步雙寫”,也就是說,只有消息同步雙寫到主從結點上時才返回寫入成功 。
異步復制: 消息寫入主節點之后就直接返回寫入成功 。
復制方式 | 優點 | 缺點 | 適應場景 |
---|---|---|---|
同步復制 | slave保證了與master一致的數據副本,如果master宕機,數據依然在slave中找到其數據和master的數據一致 | 由於需要slave確認效率上會有一定的損失 | 數據可靠性要求很高的場景 |
異步復制 | 無需等待slave確認消息是否存儲成功效率上要高於同步復制 | 如果master宕機,由於數據同步有延遲導致slave和master存在一定程度的數據不一致問題 | 數據可靠性要求一般的場景 |
通過上面的介紹,我們可以想到。如果要保證 Broker 數據最大化的不丟,需要在搭建 Broker 集群時,設置為同步刷盤、同步復制。當然,帶來了可靠性,也會一定程度降低性能。
如果想要在可靠性和性能之間做一個平衡,可以選擇,從 Broker 都是同步復制和異步刷盤。因為,刷盤比較消耗性能。
生產者會不會弄丟數據
Producer 可以設置三次發送消息重試。