消息中間件的四種投遞模式對比

消息中間件的四種投遞模式對比

消息中間件( Message Oriented Middleware,簡稱MOM)在企業開發中變得愈來愈重要。本文介紹消息中間件中的四種消息投遞模型,主要是介紹模型的核心特性,以及不一樣模型以前的區別。這四種模型分別是:緩存

  • PTP模型服務器

  • Pub/Sub模型運維

  • Partition模型ide

  • Transfer模型

其中PTP模型和Pub/Sub模型在JMS規範中有定義,消息中間件ActiveMQ就實現了JMS規範。然而一些消息中間件,並無實現JMS規範,而是本身設計出了一套模型,例如Kafka和RocketMQ就採用了Partition模型。此外業界還有一些其餘的消息投遞模型,例如Transfer模型,這是筆者本身起的名字。性能

一、PTP模型

Point-to-Point,點對點通訊模型。PTP是基於隊列(Queue)的,一個隊列能夠有多個生產者,和多個消費者。消息服務器按照收到消息的前後順序,將消息放到隊列中。隊列中的每一條消息,只能由一個消費者進行消費,消費以後就會從隊列中移除。優化

消息中間件的四種投遞模式對比

須要注意的是,儘管這裏使用Queue的概念,但並非先進入隊列消息,必定會被先消費。在存在多個下游Consumer狀況下,一些消息中間件,例如ActiveMQ,爲了提高消費能力,會將隊列中的消息分發到不一樣Consumer並行進行處理。這意味着消息發送的時候多是有序的,可是在消費的時候,就變成無序了。爲了保證消費的有序,一些MQ提供了"專有消費者」或者"排他消費者」的概念,在這種狀況下,隊列中的消息僅容許一個消費者進行消費,若是存在多個消費者,那麼從中選擇一個。可是,這意味着在消息在處理中沒有了並行性。若是消息量不少的狀況下,將會產生消息積壓。爲了解決"專有消費者」的性能問題,一些消息中間件採用分區的概念來解決性能問題,咱們將在後文進行介紹。線程

二、Pub/Sub模型

publish-and- subscribe, 即發佈訂閱模型。在Pub/Sub模型中,生產者將消息發佈到一個主題(Topic)中,訂閱了該Topic的全部下游消費者,均可以接收到這條消息。以下圖:設計

消息中間件的四種投遞模式對比

一般狀況下,一個條消息只要被消費一次就好了,那麼什麼狀況下須要全部的消費者都對這條消息進行消費呢?最典型的狀況就是須要在內存中對數據進行緩存,並須要實時進行更新。例如,筆者作過一個違禁詞系統,對用戶輸入的評論內容進行違禁詞彙檢測。這個違禁詞系統,部署了在N臺服務器上,爲了提高檢測性能,每臺機器都會將違禁詞庫全量加載到內存中,詞庫的更新,是經過發送MQ消息來完成的。因爲採用Pub/Sub模型,每臺機器的consumer,均可以接收到這條消息,直接在內存中更新敏感詞庫便可。3d

三、Partition模型

爲了解決在PTP模型下,有序消息須要經過"專有消費者」消費帶來的性能問題,一些消息中間件,如rocketmq,kafka採用了Partition模型,即分區模型,以下所示:中間件

消息中間件的四種投遞模式對比

生產者發送消息到某個Topic中時,最終選擇其中一個Partition進行發送。你能夠將Parition模型中的分區,理解爲PTP模型的隊列,不一樣的是,PTP模型中的隊列存儲的是全部的消息,而每一個Partition只會存儲部分數據。對於消息者,此時多了一個消費者組的概念,Paritition會在同一個消費者組下的消費者中進行分配,每一個消費者只消費分配給本身的Paritition。上圖演示了不一樣的消費者可能會分配到不一樣數量的Paritition。Paritition模式巧妙的將PTP模型和Pub/Sub模型結合在了一塊兒:

對於PTP模型:

一條消息只會由一個消費者進行消費,而Partition模型中每一個分區最終也只會有一個消費者進行消費。對於經過"專有消費者"來保證全局消費有序的場景,在Partition模型中,只需保證建立的Topic只有一個Partition便可,這個Paritition最終也只會分配其中一個消費者。另外,在絕大部分場景下,咱們沒有必要保證全局有序,例如一個訂單產生了3條消息,分別是訂單建立,訂單付款,訂單完成。消費時,要按照這個順序消費纔能有意義。可是訂單之間是能夠並行消費的,例如將訂單1產生的3條消息發送到Partiton 1,將訂單2產生的3條消息發送到Partition 2,如此便達到了不一樣訂單之間的並行消費。

對於Pub/Sub模型:

一條消息全部的下游消費者均可以進行消費。在Paritition模型中,只須要爲每一個消費者設置成不一樣的消費者組便可。然而,過多的消費者組,會給消息中間件運維帶來麻煩。因此一些消息中間件,結合了Partition模型和Pub/Sub模型。例如RocketMQ,支持爲消費者組設置消費模式,若是是集羣模式,就按照上述描述進行消費,若是是廣播模式,就按照Pub/Sub模型進行消費。固然,Partition模型也不全是優勢,其最大的限制在於Partition數量是固定的(雖然能夠調整),且只能夠分配給其中一個消費者。當消費者的數量大於Partition數量時,這些多出來的消費者將沒法消費到消息。一些消息中間件對此進行了優化,例如rocketmq,支持單個partition的並行消費。即在對單個消費者內,同時啓動多個線程,來消費這個Partition中的數據,固然前提是要求消息不是有序的,對於有序的消息,只能使用一個線程按順序消費這個Partition中的數據。

四、Transfer模型

Paritition模型中的消費者組概念頗有用,同一個Topic下的消息能夠由多個不一樣業務方進行消費,只要使用不一樣的消費者組便可,不一樣消費者組消費到的位置單獨記錄,互不影響。 可是,Paritition模型仍是限制了消費者數量不能多於分區數。所以,又有了另一種消費模型,筆者稱之爲Transfer模型,以下圖所示:

消息中間件的四種投遞模式對比

生產者仍是將消息發送到Topic中,針對一個Topic,能夠建立多個通道,這裏稱之爲channel。與分區不一樣的是,發送到Topic中的每條消息,都會轉發到每一個channel,所以每一個channel都有這個Topic的全量數據。固然,沒有必要把真的把消息體完整的拷貝一份到channel中,能夠只記錄一下消息元數據,表示有一條放到這個channel中了。消費者在消費消息時,必須指定從哪一個channel消費。多個消費者消費同一個channel時,每條消息只會有一個消費者消費達到,這一點與PTP模型相似。事實上,咱們能夠認爲,消費了同一個channel的消費者,就自動組成了一個消費者組。可是,與Partition模型不一樣的是,這裏沒有分區的概念,所以消費者的數量能夠是任意的。事實上,GO語言編寫的NSQ消息中間件,採用的就是這種模型。固然,這種模型與PTP同樣,也不能保證被消息有序,除非經過相似於」專用消費者」的概念。

相關文章
相關標籤/搜索