如何保證消息不被重復消費(如何保證消息消費時的冪等性)


 

重復消費可能會在什么場景下出現(以kafka為例)

 

  kafka實際上有個offset的概念,就是每個消息寫進去,都有一個offset,代表他的序號,

  然后consumer消費了數據之后,每隔一段時間,會把自己消費過的消息的offset提交一下,代表我已經消費過了,下次我要是重啟啥的,你就讓我繼續從上次消費到的offset來繼續消費吧。  

  但是凡事總有意外,就是你有時候重啟系統,直接kill進程了,再重啟。這會導致consumer有些消息處理了,但是沒來得及提交offset。

  重啟之后,少數消息會再次消費一次。  

  其實重復消費不可怕,可怕的是你沒考慮到重復消費之后,怎么保證冪等性。  

  假設你有個系統,消費一條往數據庫里插入一條,要是你一個消息重復兩次,你不就插入了兩條,這數據不就錯了?但是你要是消費到第二次的時候,自己判斷一下已經消費過了,直接扔了,不就保留了一條數據?   一條數據重復出現兩次,數據庫里就只有一條數據,這就保證了系統的冪等性   冪等性,我通俗點說,就一個數據,或者一個請求,給你重復來多次,你得確保對應的數據是不會改變的,不能出錯。

 

怎么保證消息隊列消費的冪等性?

 

如何保證MQ的消費是冪等性的,需要結合具體的業務來看  :

  比如你拿個數據要寫庫,你先根據主鍵查一下,如果這數據都有了,你就別插入了,update一下好吧 

  比如你是寫redis,那沒問題了,反正每次都是set,天然冪等性  

  比如你不是上面兩個場景,那做的稍微復雜一點,你需要讓生產者發送每條數據的時候,里面加一個全局唯一的id,類似訂單id之類的東西,然后你這里消費到了之后,先根據這個id去比如redis里查一下,之前消費過嗎?如果沒有消費過,你就處理,然后這個id寫redis。如果消費過了,那你就別處理了,保證別重復處理相同的消息即可。  

  還有比如基於數據庫的唯一鍵來保證重復數據不會重復插入多條,拿到數據的時候,每次重啟可能會有重復,因為kafka消費者還沒來得及提交offset,重復數據拿到了以后我們插入的時候,因為有唯一鍵約束了,所以重復數據只會插入報錯,不會導致數據庫中出現臟數據   

 

轉自:中華石杉Java工程師面試突擊


免責聲明!

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



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