消息隊列冪等性

原文鏈接:https://blog.csdn.net/weixin_44048532/article/details/86628234

一、什麼是冪等性
可以參考數據庫樂觀鎖機制,比如執行一條更新庫存的 SQL 語句,在併發場景,爲了性能和數據可靠性,會在更新時加上查詢時的版本,並且更新這個版本信息。可能你要對一個事情進行操作,這個操作可能會執行成百上千次,但是操作結果都是相同的,這就是冪等性。

二、消費端的冪等性保障
在海量訂單生成的業務高峯期,生產端有可能就會重複發生了消息,這時候消費端就要實現冪等性,這就意味着我們的消息永遠不會被消費多次,即使我們收到了一樣的消息。

業界主流的冪等性有兩種操作:

1.唯一 ID + 指紋碼 機制,利用數據庫主鍵去重

2.利用redis的原子性去實現

三、唯一 ID + 指紋碼 機制
大家肯定懂唯一 ID 的,就不多說了,爲什麼需要指紋碼呢?這是爲了應對用戶在一瞬間的頻繁操作,這個指紋碼可能是我們的一些規則或者時間戳加別的服務給到的唯一信息碼,它並不一定是我們系統生成的,基本都是由我們的業務規則拼接而來,但是一定要保證唯一性,然後就利用查詢語句進行判斷這個id是否存在數據庫中。

好處就是實現簡單,就一個拼接,然後查詢判斷是否重複。

壞處就是在高併發時,如果是單個數據庫就會有寫入性能瓶頸

解決方案 :根據 ID 進行分庫分表,對 id 進行算法路由,落到一個具體的數據庫,然後當這個 id 第二次來又會落到這個數據庫,這時候就像我單庫時的查重一樣了。利用算法路由把單庫的冪等變成多庫的冪等,分攤數據流量壓力,提高性能。

四、利用 redis 的原子性去實現
相信大家都知道 redis 的原子性操作,我這裏就不需要過多介紹了。

使用 redis 的原子性去實現需要考慮兩個點

一是 是否 要進行數據落庫,如果落庫的話,關鍵解決的問題是數據庫和緩存如何做到原子性? 數據庫與緩存進行同步肯定要進行寫操作,到底先寫 redis 還是先寫數據庫,這是個問題,涉及到緩存更新與淘汰的問題

二是如果不落庫,那麼都存儲到緩存中,如何設置定時同步的策略? 不入庫的話,可以使用雙重緩存等策略,保障一個消息副本,具體同步可以使用類似 databus 這種同步工具。

五、怎麼保證消息隊列消費的冪等性?
先大概說一說可能會有哪些重複消費的問題。

首先就是比如rabbitmq、rocketmq、kafka,都有可能會出現消費重複消費的問題,正常。因爲這問題通常不是mq自己保證的,是給你保證的。然後我們挑一個kafka來舉個例子,說說怎麼重複消費吧。

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

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

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

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

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

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

六、其實還是得結合業務來思考,我這裏給幾個思路:
(1)比如你拿個數據要寫庫,你先根據主鍵查一下,如果這數據都有了,你就別插入了,update一下好吧

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

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

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

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

https://blog.csdn.net/bntX2jSQfEHy7/article/details/89879459

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章