RocketMQ常見問題-如何保證消息傳遞的可靠性

        作爲一個消息中間件,RocketMQ的消息可靠性就是指確保消息數據不丟失。具體而言就是從消息在生產者產生,經過服務端投遞,一定能被消費者消費。在rocketMQ中會返回消息發送狀態碼,rocketMQ還提供了生產者事務操作
消息生產者Producer消息發送有三種方式:同步,異步,單向(Oneway)
1.同步發送 ,需要同時等待

SendResult sendResult = producer.send(message);

2.異步發送,異步線程發送出去消息,速度快//重點在SendCallback這裏 異步發送回調,可靠性在於需要根據返回結果在回調裏面處理業務。

producer.send(message, new SendCallback() {
           @Override
           public void onSuccess(SendResult sendResult) {
               System.out.printf(sendResult.getSendStatus()+"");
           }
 
           @Override
           public void onException(Throwable throwable) {
                    //根據業務處理
           }
       });

3.oneway  方式,只管發送,不在意是否成功,日誌處理一般這樣

producer.sendOneway(msg);

4.事務消息,通過實現TransactionMQProducer,並且編寫本地事務監聽器。

TransactionCheckListener transactionCheckListener

  @Override
    public TransactionSendResult sendMessageInTransaction(final Message msg,
                                                          final LocalTransactionExecuter tranExecuter, final Object arg) throws MQClientException {
        if (null == this.transactionCheckListener) {
            throw new MQClientException("localTransactionBranchCheckListener is null", null);
        }

        return this.defaultMQProducerImpl.sendMessageInTransaction(msg, tranExecuter, arg);
    }

關鍵點在於:
1.重試時Message Key必須保證唯一,因爲重試原因不確定我們無法保證消息是否已經發生過一次,Message Key唯一能最大程度保證業務的一致性
2.日誌的保存,關鍵字段,請求的操作人,時間,重試次數,請求體,返回結果(可以和請求體分開保存日誌,避免請求中斷帶來的不確定性。

Consumer保證消息可靠性  

      consume分爲集羣模式和廣播模式,消費者獲取消息的方式又分爲PUSH模式和PULL模式。首先廣播模式下每個consumer在本地管理消息,所以如何保證消息被正確消費,消費失敗如何處理都需要開發者自己關注。如果是PULL模式,那麼消息如何消費都是有開發者自己定義的。所以這都不是我們考慮的重點。消費者Consumer消費消息可靠性更多的是在討論集羣模式下PUSH方式消息的可靠性。

1.重試隊列
Consumer端因爲各種類型異常導致消費失敗,爲防止消息丟失而需要將其重新回發給Broker端消息隊列保存,稱之爲重試隊列。RocketMQ會爲每個消費組都設置一個Topic名稱爲“%RETRY%+consumerGroup”的重試隊列,用於暫時保存因爲各種異常而導致Consumer端無法消費的消息。考慮到異常恢復起來需要一些時間,會爲重試隊列設置多個重試級別,每個重試級別都有與之對應的重新投遞延時,重試次數越多投遞延時就越大。RocketMQ對於重試消息的處理是先保存至Topic名稱爲“SCHEDULE_TOPIC_XXXX”的延遲隊列中,後臺定時任務按照對應的時間進行Delay後重新保存至“%RETRY%+consumerGroup”的重試隊列中
2,.死信隊列
由於有些原因導致Consumer端長時間的無法正常消費從Broker端Pull過來的業務消息,爲了確保消息不會被無故的丟棄,那麼超過配置的“最大重試消費次數”後就會移入到這個死信隊列中。在RocketMQ中,SubscriptionGroupConfig配置常量默認地設置了兩個參數,一個是retryQueueNums爲1(重試隊列數量爲1個),另外一個是retryMaxTimes爲16。Broker端通過校驗判斷,如果超過了最大重試消費次數則會將消息移至這裏所說的死信隊列。這裏,RocketMQ會爲每個消費組都設置一個Topic命名爲“%DLQ%+consumerGroup"的死信隊列。一般在實際應用中,移入至死信隊列的消息,需要人工干預處理。

Broker端保證消息可靠性

Broker端的消息可靠性保證更多的要從架構層次來說明。常見的架構策略:

雙主雙從架構,NameServer多節點,同步雙寫,異步刷盤,消息在內存中,突然斷電消息丟失,同步刷盤可靠性更高,消息持續化到磁盤,同城雙活,異地多活,跨國多活

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