消息隊列(二)

消息隊列發送消息

MQ發送消息有三種實現方式html

  • 同步可靠發送
  • 異步可靠發送
  • 單向不可靠發送

同步可靠發送

原理:同步可靠發送是指發送方發出數據後,會等待直到接收方發回響應後才發出下一條消息。以下所示(圖來自消息隊列MQ新增3把武器)設計模式

圖來自網絡

應用場景:此種方式應用場景很是普遍,例如重要通知郵件、報名短信通知、營銷短信系統等。服務器

異步可靠發送

原理:異步可靠發送是指發送方發出數據後,不等待接受方發回響應,接着發送下一個消息。其可靠保障主要是須要發送方發送異步回調接口(SendCallback),在服務器接受到消息後回調該接口發送接收響應。以下所示(圖來自消息隊列MQ新增3把武器)
圖來自網絡微信

應用場景:異步可靠發送通常用於鏈路耗時較長,對RT響應時間較爲敏感的業務場景,例如用戶視頻上傳後通知啓動轉碼服務,轉碼完成後通知推送轉碼結果等。網絡

單向不可靠發送

原理:單向不可靠發送特色時只負責發送消息,不等待服務器迴應其也沒有回調函數的觸發,即只發送消息不等待應答。該方式發送消息過程耗時很是短。以下所示(圖來自消息隊列MQ新增3把武器)
圖來自網絡架構

應用場景:適用於某些耗時很是短且對可靠性要求不高,但對可靠性要求並不高的場景,例如日誌收集。異步

三種方式的特色和區別以下:函數

方式 發送TPS 發送結果反饋 可靠性
同步可靠發送 較快 不丟失消息
異步可靠發送 不丟失消息
單向不可靠發送 最快 可能丟失消息

消息隊列接收消息

MQ接收消息也有同步和異步的區分,這裏主要講異步的方式,其中異步主要有下面兩種方式:線程

  • Push Message(推消息)
  • Pull Message(拉消息)

這裏不論是推仍是拉,都是異步狀況下。該狀況下,MQ服務器異步發送消息給客戶端,客戶端在接收消息後會發送ACK消息給MQ服務器表示已經接收到ACK消息後刪除消息,這樣保證消息的可靠到達。設計

mark

推、拉消息

推消息(Push)主要指MQ-Server主動把消息推送給消費者,拉消息(Pull)主要指消費者主動向MQ-Server拉消息。Push、Pull主要是有如下優缺點:

1. 慢消費

慢消費指的是消費者消費消息的速度達不到生產者生成消息的速度。慢消費會形成的MQ-Server消息積壓,在Push模型下MQ-Server會一直不斷的向消費者發送消息,形成網絡積壓。而Pull模型下因爲是消費者主動向MQ-Server拉消息,因此不會形成網絡積壓。

2. 消息延遲與忙等
消息延遲和忙等主要是Pull模型形成的問題。Push模型主動權在MQ-Server這裏因此不會形成上訴問題。而因爲Pull模型主動權在消費者,消費者會主動向MQ-Server拉消息,因此出現消費者何時去Pull消息,因此會操做消息延遲。在RocketMQ中,其使用一種長輪詢的作法去Pull消息。基本思路是:消費者嘗試拉消息,若是拉取失敗則會把該鏈接wait,直到有新消息來而後notify返回新消息。

消息隊列架構

下圖是MQ的核心架構圖(圖來自微信公衆號 <架構師之路> ),注:都是異步可靠方式

圖來自微信公衆號

消息隊列核心架構分爲3塊

  1. 發送方:紅色區域,其由MQ-Client和業務調用模塊構成
  2. MQ服務器:藍色區域,其指的是Broker(消息中間件代理)
  3. 接收方:黃色區域,其由MQ-Client和業務調用模塊構成

發送方由業務調用模塊和MQ-Client-Sender組成,後者向前者提供兩個核心API:

  • sendMsg(byte[] msg)
  • sendCallback(Callback callback)

接受方由業務調用模塊和MQ-Client-Receiver組成,後者向前者提供兩個核心API:

  • ReceiveMsgCallback(byte[] bytes)
  • sendAck()

這裏有點像設計模式中的事件驅動模式,當有MQ-Client-Sender、MQ-Client-Receiver時就至關於向MQ-Server註冊這兩個事件。當MQ-Server接收到消息時回調MQ-Client-Sender事件接口以告知MQ-Client-Sender已經接收到該消息,當MQ-Server發現符合MQ-Client-Receiver的消息時,就回調MQ-Client-Receiver事件接口以發送消息。

消息隊列消息可靠性的保證

MQ須要接收生產者生成的消息並把消息傳遞給消費者進行消息消費,因此MQ須要保證消息發送和消息傳遞的可靠性。注:圖來自微信公衆號 <架構師之路>

圖來自微信公衆號<架構師之路

消息發送

  1. MQ-Client將消息發送給MQ-Server(業務方調用sendMsg())
  2. MQ-Server將消息落地(就是存放消息),落地後即爲發送成功
  3. MQ-Server發送應答給MQ-Client(MQ-Server回調Callback)

消息傳遞

  1. MQ-Server將消息發送給MQ-Client(MQ-Server回調ReceiveMsgCallback接口)
  2. MQ-Client發送應答ACK給MQ-Server(業務方調用sendAck())
  3. MQ-Server接收到ACK,將以前落地的消息刪除

由上咱們能夠看出消息發送和消息傳遞過程當中均可能發送消息丟失,因此咱們爲了保證消息的可靠性,MQ須要進行消息重傳和超時

消息發送的超時和重傳
在消息發送過程當中一、二、3可能出現消息丟失或者超時,因爲MQ-Client沒有收到回調消息,因此MQ-Client會在time時間內重發消息直到收到回調消息。須要注意的是,這裏可能形成MQ-Server收到同一消息的屢次重發,也就是形成了消息重複。

消息傳遞的超時和重傳
在消息傳遞過程當中的四、五、6可能出現消息丟失或者超時,因爲MQ-Server沒有收到Ack消息因此會形成MQ-Server重發消息,也就是形成了消息重複。

也就是說:因爲要保證消息的可靠性會致使消息重複

消息去重

由上面咱們可知在保證消息的可靠性上回致使消息的重複,而且多條消息body可能相同,因此須要咱們解決下面兩種問題:

  • 避免消息重複消費
  • 避免多條相同body的消息被過濾

本身在網絡上看了許多的方案,發現消息去重通常由業務端本身去解決,主要保證消費者消費消息的冪等性

消費消息的冪等性

咱們能夠下生產者生成消息時在消息體中插入去重key,在消費者消費消息時,經過去重key保證相同消息不會被重複消費而且保證相同body的消息不會被過濾。其中去重key能夠由<生產者IP+線程ID+時間戳+時間內遞歸值>組成惟一值。具體可見:騰訊雲關於消費去重文章

Reference

http://jm.taobao.org/2016/07/21/3-ways-to-send-message
https://tech.meituan.com/mq-design.html
https://cloud.tencent.com/document/product/406/4791 架構師之路工做號《消息總線可否實現消息必達?》(因爲微信公衆號文章URL有時間限制,因此沒有列出來)

相關文章
相關標籤/搜索