1. 程式人生 > 其它 >RabbitMQ訊息丟失、積壓、重複等解決方案

RabbitMQ訊息丟失、積壓、重複等解決方案

訊息丟失

1、只要訂單完成我們就會發送一條訊息給MQ,這個途中突然MQ伺服器網路中斷,導致訊息無法抵達

做好容錯方法需要在訊息傳送前加上異常處理

 try {
  rabbitTemplate.convertAndSend("order-event-exchange", "order.release.other", orderTo);
    } 
catch (Exception e) {
   //將沒法送成功的訊息進行重試傳送
    }

還可以將訊息存入資料庫,把失敗的訊息定期重新再發一遍

2、當訊息傳送給MQ,通過Brock通過交換機抵達佇列,MQ關機了,只有抵達佇列才能實現訊息持久化

這時候需要使用生產者的確認機制

只要訊息收到了會自動持久化,如果進入另一個回撥方法說明報錯了,需要修改資料庫使訊息重發

3、自動ACK的狀態下。消費者收到訊息,但沒來得及訊息然後宕機

一定開啟手動ACK,消費成功才移除,失敗或者沒來得及處理就noAck並重新入隊

訊息重複

1、訊息消費成功,事務已經提交,ack時,機器宕機。導致沒有ack成功,Broker的訊息重新由unack變為ready,併發送給其他消費者

在ack的時候宕機,導致訊息沒有確認,又需要重新發送

2、訊息消費失敗,由於重試機制,自動又將訊息傳送出去

關閉訂單的時候,沒有成功,又重新進入佇列再次執行,這種是可以允許的

解決辦法:

  • 消費者的業務消費介面應該設計為冪等性的。比如扣庫存有工作單的狀態標誌
  • 使用防重表(redis/mysql),傳送訊息每一個都有業務的唯一標識,處理過就不用處理
  • rabbitMQ的每一個訊息都有redelivered欄位,可以獲取是否是被重新投遞過來的,而不是第一次投遞過來的

判斷當前訊息是否是第二次及以後被派發過來的

訊息積壓

  • 消費者宕機積壓

  • 消費者消費能力不足積壓

  • 傳送者傳送流量太大

    • 上線更多的消費者,進行正常消費

    • 上線專門的佇列消費服務,將訊息先批量取出來,記錄資料庫,離線慢慢處理

這也是實現了柔性事務-可靠訊息+最終一致性解決方案

做好訊息確認機制(生產者、消費者)+手動確認機制

並把訊息在資料庫做好記錄