消息隊列怎樣不丟消息?
消息隊列的可用性的一個體現就是防止消息丟失,實現消息的必達性。
這張圖上畫出了三個角色:發送方,MQ,接收方。
發送方包括兩部分:業務調用方與MQ-client-sender,後者向前者提供了兩個API:
- SendMsg(bytes[] msg):發送消息,步驟1
- SendCallback():發送成功後的回調,步驟3
藍色的MQ核心集群又分為四個部分:MQ-server,zk,db,管理後台web
接收方包括兩部分,業務接收方與MQ-client-receiver,後者向前者提供了兩個API:
- RecvCallback(bytes[] msg):收到消息回調,步驟4
- SendAck():確認收到消息,步驟5
MQ是解耦利器,其工作過程可分成兩大部分
- 上半場:發送方將消息投遞給MQ
- 下半場:MQ把消息投給給接收方
上半場的消息必達性,是指消息從發送方client必達MQ-server
1)消息從client發送到MQ-server,發送方調用API是SendMsg(bytes[] msg)
2)MQ-server接收到消息後存儲,視為發送成功
3)MQ-server向client發送應答消息,發送方接收後調用SendCallback()
下半場的消息必達性,是指消息從MQ-server必達消息接收方
4)MQ-server將消息發送給接收方,接收方調動API:RecvCallback(bytes[] msg)
5)接收方接到消息後,向MQ-server發送應答消息,調用API:SendAck()
6)MQ-server接收到應答消息後,刪除db中的消息
MQ消息的必達性是怎麼實現的?或者說,MQ丟失了消息怎麼辦?
MQ利用超時-重發機制,保證MQ消息的必達性。
上半場的3個步驟中,如果丟失消息導致超時,那麼MQ-client-sender內的timer會重發,並希望收到3的消息。如果重試N此之後讓不能收到應答消息,那麼SendCallback回調發送失敗。
下半場的3個步驟中,如果丟失消息導致超時,那麼MQ-server內的timer會重發,希望得到5並且執行6,這個過程會採用指數退避原則,先隔x秒重發,2x秒重發,4x秒重發。
以上,可以看到MQ為了保證消息必達,架構上有兩個特點
- 消息收到先落地
- 消息超時、重傳、確認保證消息必達
2018-01-02閱:
今天讀書,MQ向消費者重發消息只是在push模式下,在pull模式下是不會的。那麼在這種模式下怎樣保證消息必達呢?
參考資料:
消息匯流排能否實現消息必達?
《大型網站系統與Java中間件實踐》
推薦閱讀:
※Python操作rabbitmq系列(二):多個接收端消費消息
※消息隊列的冪等性
※Spring 整合JMS 基於ActiveMQ 實現消息的發送接收
※調用:RPC MQ
TAG:消息隊列 |