RabbitMQ 訊息的可靠投遞
概述
可靠性投遞
- 保障訊息能夠成功發出
- 保 障rabbitmq(broker)能夠成功接收。接收指的是:broker接收到生產者傳送的訊息,放到exchange中,分發給對應的queue,交付給對應的消費者。
- 傳送端要收到broker的確認應答,確認broker已收到|處理訊息
- 完善的訊息補償機制。傳送端沒收到broker的確認應答,不知道訊息是否成功投遞成功,這時候就需要做一些補償處理,比如重新投遞。
rabbitmq的server又叫做broker,接收客戶端的連線,實現AMQP實體服務,包含exchange、queue等多種元件。
說白了,broker就是rabbitmq伺服器。
實現訊息可靠性投遞的、常見的2種解決方案
- 訊息狀態入庫,對訊息狀態進行打標
- 延時再次投遞訊息,回撥確認
方案一 訊息狀態打標
1、生產者將訊息入庫、訊息狀態入庫
比如使用者下單,產生一個Order物件,把這個Order物件資料持久化到資料庫中。
單獨用一張表來儲存訊息狀態:
用外來鍵關聯訊息(比如關聯訂單表的id),
設定一個status列記錄訊息投遞狀態,預設值為0,表示訊息未投遞到broker;
設定一個時間列,記錄訊息投遞時間;
設定一個重試次數列,記錄重新投遞的次數,預設值為0。
2、生產者傳送訊息到broker
把Order物件傳送到broker,因為訊息都要轉換為byte[ ]傳送,什麼型別都可以。
3、生產者接收到broker的確認應答,將資料庫中該條訊息的狀態修改為1,表示成功投遞
4、分散式系統的定時任務
如果訊息投遞一段時間後,未收到broker的確認應答,怎麼補償處理?
使用定時任務來做:
生產者每隔一段時間,比如5min,啟動一條執行緒來查詢資料庫中重試次數達到指定值(比如3)、且投遞時間已超過指定值(比如5min)的訊息,將其狀態修改為2,表示重試指定次數後仍未能成功投遞;
再查詢狀態為0、且傳送時間已超過指定時間的訊息,重新投遞,並更新投遞時間為當前時間、重試次數+1;
方案一存在的問題
生產者執行定時任務也有額外的開銷,生產者要進行2方面的資料庫IO操作(訊息本身+訊息狀態),IO是很花時間的,在高併發的情況下,資料庫效能很容易成為系統效能的瓶頸。
併發量大的情況下,第一種方案嚴重拉低生產者的效能。
相比之下,第二種方案用得更多,但稍微複雜一點。
方案二 延時再次投遞訊息
1、生產者將訊息入庫,並將訊息傳送給broker,broker將訊息放到對應的queue1中
2、消費者監聽queue1,處理訊息,處理一條訊息後產生一條新訊息作為確認(繫結queue2),比如以Order的id作為新訊息,總之要能唯一標識處理的訊息。
3、消費者將產生的訊息傳送給broker,broker將訊息放到queue2中(注意不是消費者監聽的queue1)
4、單獨寫一個callback service(回撥服務),來監聽queue2,把queue2中的訊息入庫,比如放在tb_msg_processed表中,一條記錄代表一條已被消費者處理的訊息
5、生產者傳送訊息後,延時再次傳送這條訊息(繫結queue3),比如3min|5min後再次傳送這條訊息。
6、回撥服務監聽queue3,把queue中訊息與資料庫中的記錄對比,比如把queue3獲取到的Order的id取出來,查詢tb_msg_processed中有沒有這個Order id,有就說明投遞成功;沒有就說說明未投妥,回撥服務rpc通知生產者(傳遞order id),生產者從資料庫查詢該條訊息的資料(order物件),重新投遞(queue1)——重新走一遍流程。
第一種方案消費者使用資料包來確認應答(ack),第二種由消費者自己產生一條訊息來確認應答。
整個流程中,生產者又叫做upstream service(上游服務),消費者又叫做downstream service(下游服務)。
方案二的優缺點
相較於第一種方案,第二種方案多寫一個服務,每對生產者——消費者都使用一個額外的queue來確認,回撥服務開發成本高些、略微複雜些;
部署回撥服務又要使用、維護額外的機器,成本變高了。
但生產者的資料庫IO操作減少了,提升了效能。只要效能上去,稍微增加點成本完全可以接受。
說明
(1)訊息入庫完成,然後傳送訊息(Order物件)到broker,注意順序
(2)分散式事務對效能的影響很大,併發量中小的可以加事務,如果併發量很大,事務會嚴重拉低效能,不建議加事務(能不加就不加)
(3)不管是第一種、還是第二種,都很難做到100%的投遞成功。優先考慮能夠扛得住高併發(效能),在保證效能的前提下儘可能提高訊息投遞的可靠性
相關文章
- Rabbitmq可靠訊息投遞,訊息確認機制MQ
- 訊息中介軟體RabbitMQ可靠性投遞與生產實踐MQ
- 實現rabbitmq訊息重新投遞方案MQ
- RabbitMQ的訊息可靠性(五)MQ
- java從SQS訂閱訊息 的demo, 要求保證訊息可靠投遞的例子Java
- 《RabbitMQ》如何保證訊息的可靠性MQ
- SpringBoot 整合 RabbitMQ 實現訊息可靠傳輸Spring BootMQ
- RabbitMQ高階之如何保證訊息可靠性?MQ
- RabbitMQ 和訊息傳遞常用一些術語MQ
- 阿里IM技術分享(四):閒魚億級IM訊息系統的可靠投遞優化實踐阿里優化
- RabbitMQ訊息模式MQ模式
- 如何透過 SpringBoot+RabbitMQ 保證訊息100%投遞成功並被消費?(附原始碼)Spring BootMQ原始碼
- vue---元件間傳遞訊息(父子傳遞訊息,兄弟傳遞訊息)Vue元件
- Apache Kafka和Spring Boot的容錯和可靠訊息傳遞 – Arnold GalovicsApacheKafkaSpring Boot
- RabbitMQ 100% 投遞成功方案詳解MQ
- 用於實時訊息傳遞和通知的 RabbitMQ 和 SpringBoot原始碼MQSpring Boot原始碼
- Go 微服務:基於 RabbitMQ 和 AMQP 進行訊息傳遞Go微服務MQ
- [訊息佇列]RabbitMQ佇列MQ
- RabbitMQ訊息佇列MQ佇列
- RabbitMQ訊息佇列(五):Routing 訊息路由MQ佇列路由
- 訊息佇列之如何保證訊息的可靠傳輸佇列
- MQ訊息佇列_RabbitMQMQ佇列
- RabbitMq之訊息確認MQ
- SpringBoot2--RabbitMQ訊息Spring BootMQ
- 訊息中介軟體rabbitMQMQ
- 訊息佇列之RabbitMQ佇列MQ
- rabbitmq訊息佇列原理MQ佇列
- RabbitMQ防止訊息丟失MQ
- RabbitMQ訊息佇列(九):Publisher的訊息確認機制MQ佇列
- RabbitMQ實戰:理解訊息通訊MQ
- 【原創】訊息佇列的消費語義和投遞語義佇列
- SpringBoot:初探 RabbitMQ 訊息佇列Spring BootMQ佇列
- RabbitMQ 訊息確認機制MQ
- Chrome Extension 訊息傳遞Chrome
- Flutter中訊息傳遞Flutter
- RabbitMQ的 RPC 訊息模式你會了嗎?MQRPC模式
- 訊息佇列的使用場景之RabbitMQ佇列MQ
- RabbitMQ如何保證訊息的可達性MQ