訊息佇列 怎麼處理訊息佇列中重複的資料

2021-09-29 20:05:48 字數 1105 閱讀 7969

在分布式系統中,上游發來的訊息佇列必然會存在重複的資料,這是不可避免的。

producer在傳送訊息時比如遇到網路問題時,傳送後因超時得不到伺服器的ack,從而進行重發。如果傳送的訊息內容是銀行扣款,那麼發生的問題可想而知。

有人會問為啥中介軟體不能幫我們做排重?

中介軟體排重會有以下問題:

名稱質量標準

kafka

at least once

rocketmq

at least once

rabbitmq

at least once

這裡說個專業名詞:

冪等(idempotence) 本來是乙個數學上的概念,它是這樣定義的:如果乙個函式 f(x) 滿足:f(f(x)) = f(x),則函式 f(x) 滿足冪等性。

這個概念被拓展到計算機領域,被用來描述乙個操作、方法或者服務。乙個冪等操作的特點是,其任意多次執行所產生的影響均與一次執行的影響相同

那麼回到一開始提到的問題:銀行轉賬多次收到扣款的問題。如果我們保證了消費的業務**是冪等的,那麼無論多少重複的訊息過來,依然與第一次執行的發生的效果一致,這個問題就迎刃而解。

那怎麼實現冪等性呢?一般有以下幾種辦法。

使用資料庫唯一索引來實現冪等

通俗點說就是每次操作都有相同的乙個操作id,在操作之前做查詢,如果該操作id執行過,就避免再次執行。

比如在資料庫對這個唯一約束增加唯一索引,多次插入相同的資料時會直接丟擲異常「org.springframework.dao.duplicatekeyexception」。或者直接使用「insert if not exist」來避免多次插入資料。

使用token 機制或者 guid(全域性唯一 id)機制

和資料庫生成唯一標識的概念是一致的,如果訊息量過多都放入資料庫中去判斷的話,可能會造成資料庫奔潰。

那麼在訊息消費時,先判斷該訊息是否已經消費過,如果沒有消費過,才放入到下一步進行持久化操作。

但是在分布式系統中,多個節點可能無法互相感知各自的消費訊息,可能會出現這樣的情況:

訊息佇列如何處理重複訊息

一 訊息重複現象 在 mqtt 協議中,給出了三種傳遞訊息時能夠提供的服務質量標準 at most once 最多一次,這種情況會丟失部分資料,一般日誌收集這種對資料不嚴格的可以使用 at least once 最少一次,這種會導致一條訊息重 送 exactly once 正好一次,一條訊息只會被消...

訊息佇列 訊息佇列

輪詢排程 一次性分發所有訊息,保證訊息平均分配,不管消費者是否能正常消費 訊息應答 保證消費端能確實消費,不丟失 公平 乙個乙個分發所有訊息,在保證分發到的執行緒確認回覆後,才分發下個訊息給下個空閒的消費者,訊息持久化 保證佇列中的訊息不丟失,包括3要素 交換器 訊息佇列 訊息都必須宣告持久化 發布...

訊息佇列 訊息佇列 kafka

kafka是乙個分布式的基於發布 訂閱模式的訊息佇列,主要用於大資料實時處理領域。要理解kafka首先要有分布式的概念,要有訊息佇列的概念。分布式系統最大的優勢就是解耦和削峰,這種情況下,a系統生成了乙個訊息,b系統非同步獲取,那麼就需要乙個存放訊息的訊息佇列 mq 相比較傳統的訊息佇列,訊息被消費...