RabbitMQ訊息丟失、積壓、重複等解決方案
阿新 • • 發佈:2021-10-24
訊息丟失
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欄位,可以獲取是否是被重新投遞過來的,而不是第一次投遞過來的
判斷當前訊息是否是第二次及以後被派發過來的
訊息積壓
-
消費者宕機積壓
-
消費者消費能力不足積壓
-
傳送者傳送流量太大
-
上線更多的消費者,進行正常消費
-
上線專門的佇列消費服務,將訊息先批量取出來,記錄資料庫,離線慢慢處理
-
這也是實現了柔性事務-可靠訊息+最終一致性解決方案
做好訊息確認機制(生產者、消費者)+手動確認機制
並把訊息在資料庫做好記錄