RocketMQ學習筆記(14)----RocketMQ的去重策略


1. Exactly Only Once

  (1). 發送消息階段,不允許發送重復的消息

  (2). 消費消息階段,不允許消費重復的消息。

  只有以上兩個條件都滿足情況下,才能認為消息是“Exactly Only Once”,而要實現以上兩點,在分布式系統環

  境下,不可避免要產生巨大的開銷。所以RocketMQ 為了追求高性能,並不保證此特性,要求在業務上進行去重,也就是說消費消息要做到冪等性。RocketMQ 雖然不能嚴格保證不重復,但是正常情況下很少會出現重復發送、消

費情況,只有網絡異常,Consumer 啟停等異常情況下會出現消息重復。

  此問題的本質原因是網絡調用存在不確定性,即既不成功也不失敗的第三種狀態,所以才產生了消息重復性問
題。

2. 重復消費的原因

  在於回饋機制。正常情況下,消費者在消費消息時候,消費完畢后,會發送一個ACK確認信息給消息隊列(broker),消息隊列(broker)就知道該消息被消費了,就會將該消息從消息隊列中刪除。

不同的消息隊列發送的確認信息形式不同,例如RabbitMQ是發送一個ACK確認消息,RocketMQ是返回一個CONSUME_SUCCESS成功標志,kafka實際上有個offset的概念。

  造成重復消費的原因?,就是因為網絡原因閃斷,ACK返回失敗等等故障,確認信息沒有傳送到消息隊列,導致消息隊列不知道自己已經消費過該消息了,再次將該消息分發給其他的消費者。(因為消息重試等機制的原因,如果一個consumer斷了,rocketmq有consumer集群,會將該消息重新發給其他consumer)

3. 去重策略

  去重原則:1.冪等性 2.業務去重

  冪等性:(處理必須唯一) 無論這個業務請求被(consumer)執行多少次,我們的數據庫的結果都是唯一的,不可變的。

  去重策略:去重表機制,業務拼接去重策略(比如唯一流水號)

  1.建立一個消息表,拿到這個消息做數據庫的insert操作。給這個消息做一個唯一主鍵(primary key)或者唯一約束,那么就算出現重復消費的情況,就會導致主鍵沖突。

    高並發下去重:采用Redis去重(key天然支持原子性並要求不可重復),但是由於不在一個事務,要求有適當的補償策略,但是對於很重要的業務,不應該支持補償

  2.利用redis事務,主鍵(我們必須把全量的操作數據都存放在redis里,然后定時去和數據庫做數據同步)—-即消費處理后,該處理本來應該保存在數據庫的,先保存在redis,再通過一定業務方式從redis中取數據進行db持久化

  3.利用redis和關系型數據庫一起做去重機制

  4.拿到這個消息做redis的set的操作.redis就是天然冪等性 

  5.准備一個第三方介質,來做消費記錄。以redis為例,給消息分配一個全局id,只要消費過該消息,將 < id,message>以K-V形式寫入redis。那消費者開始消費前,先去redis中查詢有沒消費記錄即可。


免責聲明!

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



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