全部產品
Search
文件中心

ApsaraMQ for RocketMQ:訊息等冪

更新時間:Jul 01, 2024

為了防止訊息重複消費導致業務處理異常,雲訊息佇列 RocketMQ 版的消費者在接收到訊息後,有必要根據業務上的唯一Key對訊息做等冪處理。本文介紹訊息等冪的概念、適用情境以及處理方法。

什麼是訊息等冪

當出現消費者對某條訊息重複消費的情況時,重複消費的結果與消費一次的結果是相同的,並且多次消費並未對業務系統產生任何負面影響,那麼這個消費者的處理過程就是等冪的。

例如,在支付情境下,消費者消費扣款訊息,對一筆訂單執行扣款操作,扣款金額為100美元。如果因網路不穩定等原因導致扣款訊息重複投遞,消費者重複消費了該扣款訊息,但最終的業務結果是只扣款一次,計費100美元,且使用者的扣款記錄中對應的訂單只有一條扣款流水,不會多次扣除費用。那麼這次扣款操作是符合要求的,整個消費過程實現了訊息等冪。

適用情境

在互連網應用中,尤其在網路不穩定的情況下,雲訊息佇列 RocketMQ 版的訊息有可能會出現重複。如果訊息重複會影響您的業務處理,請對訊息做等冪處理。

訊息重複的情境如下:

  • 發送時訊息重複

    當一條訊息已被成功發送到服務端並完成持久化,此時出現了網路閃斷或者用戶端宕機,導致服務端對用戶端應答失敗。 如果此時生產者意識到訊息發送失敗並嘗試再次發送訊息,消費者後續會收到兩條內容相同但Message ID不同的訊息。

  • 投遞時訊息重複

    訊息消費的情境下,訊息已投遞到消費者並完成業務處理,當用戶端給服務端反饋應答的時候網路閃斷。為了保證訊息至少被消費一次,雲訊息佇列 RocketMQ 版的服務端將在網路恢複後再次嘗試投遞之前已被處理過的訊息,消費者後續會收到兩條內容相同並且Message ID也相同的訊息。

  • 負載平衡時訊息重複(包括但不限於網路抖動、Broker重啟以及消費者應用重啟)

    雲訊息佇列 RocketMQ 版的Broker或用戶端重啟、擴容或縮容時,會觸發Rebalance,此時消費者可能會收到少量重複訊息。

處理方法

因為不同的Message ID對應的訊息內容可能相同,有可能出現衝突(重複)的情況,所以真正安全的等冪處理,不建議以Message ID作為處理依據。最好的方式是以業務唯一標識作為等冪處理的關鍵依據,而業務的唯一標識可以通過訊息Key設定。

以支付情境為例,可以將訊息的Key設定為訂單號,作為等冪處理的依據。具體程式碼範例如下:

Message message = new Message();
message.setKey("ORDERID_100");
SendResult sendResult = producer.send(message);           

消費者收到訊息時可以根據訊息的Key,即訂單號來實現訊息等冪:

consumer.subscribe("ons_test", "*", new MessageListener() {
    public Action consume(Message message, ConsumeContext context) {
        String key = message.getKey()
        // 根據業務唯一標識的Key做等冪處理。
    }
});