消息隊列:RocketMQ消息順序和消息重複

消息順序

消息順序是隻可以按照消息發送的順序進行消費。一個訂單產生3條消息,訂單創建、付款、訂單完成。消費時只有按照順序消費才有意義,不可能先消費付款消息再消費訂單創建消息,這樣就亂了。另外,多筆訂單又可以並行消費。如何保證呢?

一個訂單產生的消息只能發送給同一個MQ服務器中的同一個分區,並且按順序發送,這樣才能在理論上保證消費者消費時是按照順序消費的,因為一個分區就是一個邏輯隊列。生產者雖然按順序發送,但是第一條消息到達MQ的耗時比第二條多,那麼第二條則會被先消費,這樣就又導致消費時不是順序的。那麼如何解決呢?可以採取只有第一條被消費者消費成功後再發送第二條。看下圖:

但是如果第一條被髮送到消費者後,消費者沒有響應(消費者發送響應但是因為網絡問題丟失或者消費者就沒有收到消息),那麼在這種情況下你是繼續發送第二條還是重發第一條呢?如果是嚴格消息順序,那肯定是重發第一條,但是如果是消費者消費後的響應丟失了,那麼重發第一條就會造成重複消費。

從另外一方面看,如果不考慮網絡異常,那麼要實現嚴格消息,就必須採取一種一對一關係,生產者A的消息對應到MQ服務器1的X隊列,消費者A消費X隊列。這樣串行結構就會造成系統吞吐量太低;更多異常需要處理比如消費端出現問題,那麼整個消息隊列就會出現阻塞。RocketMQ通過輪詢所有隊列來確定消息發送到哪一個隊列(負載均衡),比如相同訂單號的消息會被先後發送到統一隊列中。所以RocketMQ

消息重複

造成消費重複的根本原因是網絡不可達,只要有網絡,這種網絡的不穩定因素就存在你無法規避。所以解決這個問題的最好辦法就是繞過它。這就變成了,消費端收到兩個一樣的消息後如何處理,而不是從發送端解決不發送2個一樣的消息。對於消費端的要求就是:

  • 消費端處理業務消息要保持冪等性,也就是同一個東西執行多次會得到相同結果
  • 保證每條消息都有唯一編號切保證消息處理成功與去重表的日誌同時出現

第一條好理解,第二條就是利用一張日誌表來記錄已經處理成功的消息ID,如果新到的消息ID已經存在表中那麼就不再處理這個消息。第一條是在消費端實現的,不屬於消息系統的功能;第二條可以是消息系統實現也可以是業務端實現,處於對消息系統的吞吐量和高可用考慮最好還是由消費端去處理。所以這也就是RocketMQ不解決消息重複的原因。


分享到:


相關文章: