1. 程式人生 > >MQ如何解決消息的順序問題和消息的重復問題?

MQ如何解決消息的順序問題和消息的重復問題?

自己 最終 消費者 嚴格 問題: 日誌 消費 分布式消息 rgba

一、摘要

分布式消息系統作為實現分布式系統可擴展、可伸縮性的關鍵組件,需要具有高吞吐量、高可用等特點。而談到消息系統的設計,就回避不了兩個問題:

1、消息的順序問題

2、消息的重復問題

二、關鍵特性以及其實現原理

2.1、順序消息

要實現嚴格的順序消息,簡單且可行的辦法就是:

保證生產者 - MQServer - 消費者是一對一對一的關系

這樣的設計雖然簡單易行,但也會存在一些很嚴重的問題,比如:

1、並行度就會成為消息系統的瓶頸(吞吐量不夠)

2、更多的異常處理,比如:只要消費端出現問題,就會導致整個處理流程阻塞,我們不得不花費更多的精力來解決阻塞的問題。

但我們的最終目標是要集群的高容錯性和高吞吐量。這似乎是一對不可調和的矛盾,那麽阿裏是如何解決的?

有些問題,看起來很重要,但實際上我們可以通過合理的設計或者將問題分解來規避。如果硬要把時間花在解決問題本身,實際上不僅效率低下,而且也是一種浪費。從這個角度來看消息的順序問題,我們可以得出兩個結論:

1、不關註亂序的應用實際大量存在

2、隊列無序並不意味著消息無序

2.2、消息重復

上面在解決消息順序問題時,引入了一個新的問題,就是消息重復。那麽MQ是怎樣解決消息重復的問題呢?還是“恰好”不解決。

造成消息的重復的根本原因是:網絡不可達。只要通過網絡交換數據,就無法避免這個問題。所以解決這個問題的辦法就是不解決,轉而繞過這個問題。那麽問題就變成了:如果消費端收到兩條一樣的消息,應該怎樣處理?

1、消費端處理消息的業務邏輯保持冪等性

2、保證每條消息都有唯一編號且保證消息處理成功與去重表的日誌同時出現

第1條很好理解,只要保持冪等性,不管來多少條重復消息,最後處理的結果都一樣。第2條原理就是利用一張日誌表來記錄已經處理成功的消息的ID,如果新到的消息ID已經在日誌表中,那麽就不再處理這條消息。

我們可以看到第1條的解決方式,很明顯應該在消費端實現,不屬於消息系統要實現的功能。第2條可以消息系統實現,也可以業務端實現。正常情況下出現重復消息的概率不一定大,且由消息系統實現的話,肯定會對消息系統的吞吐量和高可用有影響,所以最好還是由業務端自己處理消息重復的問題,這也是MQ不解決消息重復的問題的原因。

MQ不保證消息不重復,如果你的業務需要保證嚴格的不重復消息,需要你自己在業務端去重。

MQ如何解決消息的順序問題和消息的重復問題?