分佈式消息隊列:如何保證消息不被重複消費?(消息隊列消費的冪等性)

怎麼保證消息不被重複消費?(消息隊列消費的冪等性)

先大概說一說可能會有哪些重複消費的問題。首先就是好比rabbitmq、rocketmq、kafka,都有可能會出現消費重複消費的問題,正常。由於這問題一般不是mq本身保證的,是給你保證的。而後咱們挑一個kafka來舉個例子,說說怎麼重複消費吧。redis

kafka實際上有個offset的概念,就是每一個消息寫進去,都有一個offset,表明他的序號,而後consumer消費了數據以後,每隔一段時間,會把本身消費過的消息的offset提交一下,表明我已經消費過了,下次我要是重啓啥的,你就讓我繼續從上次消費到的offset來繼續消費吧。數據庫

可是凡事總有意外,好比咱們以前生產常常遇到的,就是你有時候重啓系統,看你怎麼重啓了,若是碰到點着急的,直接kill進程了,再重啓。這會致使consumer有些消息處理了,可是沒來得及提交offset,尷尬了。重啓以後,少數消息會再次消費一次。分佈式

其實重複消費不可怕,可怕的是你沒考慮到重複消費以後,怎麼保證冪等性。post

舉個例子,假設你有個系統,消費一條往數據庫裏插入一條,要是你一個消息重複兩次,你不就插入了兩條,這數據不就錯了?可是你要是消費到第二次的時候,本身判斷一下已經消費過了,直接扔了,不就保留了一條數據?cdn

一條數據重複出現兩次,數據庫裏就只有一條數據,這就保證了系統的冪等性冪等性,blog

通俗點說,就一個數據,或者一個請求,給你重複來屢次,你得確保對應的數據是不會改變的,不能出錯。 rabbitmq

其實還得結合業務來思考,在這給幾個思路:

  1. 好比你拿個數據要寫庫,你先根據主鍵查一下,若是這數據都有了,你就別插入了,update一下
  2. 好比你是寫redis,那沒問題了,反正每次都是set,自然冪等性
  3. 好比你不是上面兩個場景,那作的稍微複雜一點,你須要讓生產者發送每條數據的時候,裏面加一個全局惟一的id,相似訂單id之類的東西,而後你這裏消費到了以後,先根據這個id去好比redis裏查一下,以前消費過嗎?若是沒有消費過,你就處理,而後這個id寫redis。若是消費過了,那你就別處理了,保證別重複處理相同的消息便可。

還有好比基於數據庫的惟一鍵來保證重複數據不會重複插入多條,咱們以前線上系統就有這個問題,就是拿到數據的時候,每次重啓可能會有重複,由於kafka消費者還沒來得及提交offset,重複數據拿到了之後咱們插入的時候,由於有惟一鍵約束了,因此重複數據只會插入報錯,不會致使數據庫中出現髒數據隊列

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

更多系列文章

分佈式消息隊列:如何保證消息隊列的高可用
get

分佈式消息隊列:如何保證消息不被重複消費

分佈式消息隊列:如何保證消息的可靠性傳輸

最後

後續會持續更新分佈式知識,你們以爲不錯能夠點個贊在關注下,之後還會分享更多文章!

相關文章
相關標籤/搜索