分佈式通信之消息隊列

前言

上一篇介紹了分佈式通信技術中的發佈訂閱。總結來說,發佈訂閱就是發佈者產生數據到消息中心,訂閱者訂閱自己感興趣的消息,消息中心根據訂閱者的訂閱情況,將相關消息或數據發送給對應的訂閱者。在實際使用場景中,還有一種常用的通信方式,就是將消息或數據放到一個隊列裏,誰需要誰就去隊列裏面取。在分佈式領域中,這種模式叫“消息隊列”。

什麼是消息隊列?

在學術電子論文訂閱的例子中,出版社或會議方將論文發佈到論文網站(或平臺)上,然後論文網站再將論文推送給訂閱相關論文的老師或學生。這裏的論文網站就是消息中心,負責根據訂閱信息將論文送貨上門,角色非常關鍵。但其實,除了將論文送貨上門外,我們還能想到另外一種模式,也就是出版社或會議方將論文發佈到論文網站進行存儲,老師或學生根據需要到論文網站按需購買文章。這種思想,在分佈式通信領域中稱爲消息隊列模式論文網站充當的就是消息隊列的角色,也非常關鍵。
比如,很多系統都提供了用戶註冊功能,註冊完成後發送通知郵件。如下圖所示,假設用戶通過郵箱進行註冊,填寫完註冊信息並點擊提交後,系統的處理過程主要分爲兩步:

  1. 檢查用戶註冊信息的合法性,如果合法則將註冊信息寫入數據庫中,若不合法,直接返回,流程結束;
  2. 將用戶註冊信息寫入數據庫後,給用戶發送通知郵件,以告知用戶註冊的相關信息,比如註冊賬號等信息。

假設,系統將註冊信息寫入數據庫需要花費 400ms、給用戶發送通知郵件需要花費 600ms。
在這裏插入圖片描述
這時,註冊消息寫入數據庫和發送通知郵件這兩個組件間是直接交互,且是同步通信方式。那麼,從用戶提交註冊到收到響應,需要等系統完成這兩個步驟。也就是說,如果不考慮通信延遲的話,註冊系統對用戶的響應時間是 1000ms,即 1s。

如下圖所示,如果引入消息隊列作爲註冊消息寫入數據庫和發送通知郵件這兩個組件間的中間通信者,那麼這兩個組件就可以實現異步通信、異步執行。引入消息隊列後,上述步驟可以分爲三步:
在這裏插入圖片描述

  1. 檢查用戶註冊信息的合法性,如果合法則將註冊信息寫入數據庫中,若不合法則直接返回,流程結束;
  2. 註冊消息寫入消息數據庫後,將消息寫入消息隊列的隊尾;
  3. 發送通知郵件的組件去消息隊列取出隊首的消息,給用戶發送通知郵件,告知用戶註冊的相關信息。

也就是說,採用消息隊列模式,只需要第 2 步完成,即可給用戶返回響應。第 3 步發送通知郵件可以在返回響應之後執行。

用戶的註冊信息寫入數據庫之後,通過數據庫的可靠性設計來保證用戶註冊信息不會丟失,也就是說發送通知郵件的組件一定可以獲取到用戶註冊信息,即保證會給註冊用戶發送通知郵件。即,消息隊列的引入不會影響用戶註冊網站,但會提升用戶響應效率。

通常情況下,將消息寫入消息隊列的速度很快,假設需要 100ms。那麼,引入消息隊列後,發送通知郵件實現了異步讀取,系統響應時間縮短爲 500ms,響應速度提升了一倍,提升了用戶體驗。
講完了用戶註冊這個例子,我們再來看消息隊列的定義就比較容易理解了。

隊列是一種具有先進先出特點的數據結構,消息隊列是基於隊列實現的,存儲具有特定格式的消息數據,比如定義一個包含消息類型、標誌消息唯一性的 ID、消息內容的一個結構體作爲消息數據的特定格式。消息以特定格式放入這個隊列的尾部後可以直接返回,並不需要系統馬上處理,之後會有其他進程從隊列頭部開始讀取消息,按照消息放入的順序逐一處理。
從上面的例子中,我們也可以看出引入消息隊列的好處是,提高響應速度,以及實現組件間的解耦

消息隊列的原理

消息隊列工作原理

消息隊列的核心結構,如下圖所示。與發佈訂閱模式類似,消息隊列模式也是包括 3 個核心部分:

  1. 生產者。生產者會產生消息或數據,並將消息或數據插入到消息隊列中。
  2. 消息隊列。一種具有先進先出特點的數據結構,用於存儲消息。
  3. 消費者。從消息隊列中獲取消息或數據,進行相關處理。

具體流程是,生產者將發送的消息插入消息隊列,也就是入隊,之後會有一個消費者從消息隊列中逐次取出消息進行處理,完成出隊。
在這裏插入圖片描述

RocketMQ 消息隊列原理及工作機制

首先,我們看一下 RocketMQ 的架構圖,形成一個整體認知。
在這裏插入圖片描述
RokcetMQ 共包括 NameServer Cluster、Producer Cluster、Broker Cluster 和 Consumer Cluster 共 4 部分。

NameServer Cluster,指的是名字服務器集羣。這個集羣的功能與 Kafka 中引入的 ZooKeeper 類似,提供分佈式服務的協同和管理功能,在 RocketMQ 中主要是管理 Broker 的信息,包括有哪些 Broker、Broker 的地址和狀態等,以方便生產者獲取 Broker 信息發佈消息,以及訂閱者根據 Broker 信息獲取消息。

Producer Cluster,指的是生產者集羣,負責接收用戶數據,然後將數據發佈到消息隊列中心 Broker Cluster。那麼,生產者按照集羣的方式進行部署,好處是什麼呢?可以概括爲以下兩點:

  • 一是,多個 Producer 可以併發接收用戶的輸入數據,提升業務處理效率;
  • 二是,考慮到可靠性問題,如果只有一個 Producer 接收用戶輸入數據,當這個 Producer 故障後,整個業務就無法運行了。

Consumer Cluster,指的是消費者集羣,負責從 Broker 中獲取消息進行消費。Consumer 以集羣方式進行部署的好處是,提升消費者的消費能力,以避免消息隊列中心存儲溢出,消息被丟棄。
Broker Cluster,指的是 Broker 集羣,負責存儲 Producer Cluster 發佈的數據,以方便消費者進行消費。Broker Cluster 中的每個 Broker 都進行了主從設計,即每個 Broker 分爲 Broker Master 和 Broker Slave,Master 既可以寫又可以讀,Slave 不可以寫只可以讀。每次 Broker Master 會把接收到的消息同步給 Broker Slave,以實現數據備份。一旦 Broker Master 崩潰了,就可以切換到 Broker Slave 繼續提供服務。這種設計的好處是,提高了系統的可靠性。

可以看出,Broker Cluster 就是我們今天要講的核心“消息隊列中心”,接下來,我們就一起看看 Broker Cluster 的實現方式。如下圖所示,在 Broker Cluster 中,消息的存儲採用主題(Topic)+ 消息隊列(Queue)的方式實現
在這裏插入圖片描述
與 Kafka 一樣,RocketMQ 中的主題也是一個邏輯概念。一個主題可以分區,分佈在各個不同的 Broker 中,每個 Broker 上只有該主題的部分數據。每個主題分區中,隊列的數量可以不同,由用戶在創建主題時指定。隊列是資源分配的基本單元,消息進行存儲時會存放到相應主題的分區中

上面我爲你介紹了 RocketMQ 的關鍵組件。接下來,我們再看看 RocketMQ 的工作流程,如下圖所示:
在這裏插入圖片描述

  1. 首先啓動 NameServer,然後啓動 Broker。Broker 啓動後,會主動找 NameServer建立連接,並將自己的信息註冊到 NameServer 上。註冊完畢後,Broker 會週期性地給 NameServer發送心跳包,比如每隔 1s 發送一次,以告知 NameServer 自己還活着;心跳包裏還可以包括 Broker當前存儲的數據信息,也就是說 Broker 可以週期性地向 NameServer 更新自己的數據信息,以保證 NameServer上存儲的數據是最新的。
  2. 創建主題,並確定這個主題的數據放入哪些 Broker 中。
  3. 當 Producer 生產消息發送到主題時,需要先NameServer 查詢該主題存放在哪些 Broker 中,獲取到相關 Broker 信息後,將消息發送給這些 Broker進行存儲。
  4. Consumer 要從主題消費消息,也需要首先到 NameServer 查詢一下該主題的消息存儲在哪些 Broker上,然後去相應的 Broker 獲取消息進行消費。

消息隊列模式適用於什麼場景

消息隊列模式,是根據消費者需求到消息隊列獲取數據消費的,消費者只需要知道消息隊列地址即可,消息隊列中心也無需提前知道消費者信息。也就是說,這種模式對消費者沒有特別需求,因此比較適合消費者爲臨時用戶的場景

比如目前,阿里內部將 RocketMQ 應用於購物交易、充值、消息推送等多個場景,因爲在這些場景下,每個消費者不是常駐進程或服務,幾乎都是臨時存在。此外,滴滴、聯想等公司也都有采用 RocketMQ。

發佈訂閱和消息隊列模式系統解耦模式區別

概括地說,發佈訂閱和消息隊列模式雖然都支持系統解耦,但它們在實現時採用的數據結構方式並不相同。

  • 首先,數據結構:發佈訂閱模式採用了消息中心,消息隊列模式採用了消息隊列中心,它們均用來存儲生產者發佈的數據,並均有主題、Broker 等概念;唯一不同之處,是消息隊列模式中採用了具有先進先出特徵的隊列結構進行存儲,而訂閱發佈採用了 map 或數組等方式存儲。
  • 然後,我們再看看它們實現解耦的方式。消息隊列模式中,生產者發佈數據到消息隊列中心,消息隊列中心會存儲數據,等待消費者按需獲取數據。這樣生產者就不需要和消費者進行直接通信了,實現了生產者和消費者的解耦。而在發佈訂閱模式中,消費者需要提前向消息中心訂閱自己感興趣的數據,待生產者發佈數據到消息中心後,消息中心根據訂閱者訂閱信息將數據主動推送給消費者,也實現了消費者和生產者的解耦。對於消息隊列模式,消息隊列中心無需提前獲取消費者信息,因此對消費者比較靈活,適合消費者爲臨時用戶的場景而發佈訂閱模式,需要消費者提前向消息中心訂閱消息,也就是說消息中心需要提前獲取消費者信息,比較適合消費者爲長駐進程或服務的場景

總結

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章