消息隊列深入解析

消息隊列和消息

「消息隊列」(Message queue)是在消息的傳輸過程中保存消息的容器。「消息」 是在兩台計算機間傳送的數據單位。消息可以非常簡單,例如只包含文本字元串;也可以更複雜,可能包含嵌入對象。

常見的消息隊列有那些?

當前使用較多的消息隊列有RabbitMQActiveMQRocketMQKafka等等,我們之前提高的redis資料庫也可以實現消息隊列,不過不推薦,redis本身設計就不是用來做消息隊列的。

使用消息隊列的場景和好處

《大型網站技術架構》第四章和第七章均有提到消息隊列對應用性能及擴展性的提升。

1.通過非同步處理提高系統性能

如上圖,在不使用消息隊列伺服器的時候,用戶的請求數據直接寫入資料庫,在高並發的情況下資料庫壓力劇增,使得響應速度變慢。但是在使用消息隊列之後,用戶的請求數據發送給消息隊列之後立即 返回,再由消息隊列的消費者進程從消息隊列中獲取數據,非同步寫入資料庫。由於消息隊列伺服器處理速度快於資料庫(消息隊列也比資料庫有更好的伸縮性),因此響應速度得到大幅改善。

通過以上分析我們可以得出消息隊列具有很好的削峰作用的功能——即通過非同步處理,將短時間高並發產生的事務消息存儲在消息隊列中,從而削平高峰期的並發事務。 舉例:在電子商務一些秒殺、促銷活動中,合理使用消息隊列可以有效抵禦促銷活動剛開始大量訂單湧入對系統的衝擊。如下圖所示:

因為用戶請求數據寫入消息隊列之後就立即返回給用戶了,但是請求數據在後續的業務校驗、寫資料庫等操作中可能失敗。因此使用消息隊列進行非同步處理之後,需要適當修改業務流程進行配合,比如用戶在提交訂單之後,訂單數據寫入消息隊列,不能立即返回用戶訂單提交成功,需要在消息隊列的訂單消費者進程真正處理完該訂單之後,甚至出庫後,再通過電子郵件或簡訊通知用戶訂單成功,以免交易糾紛。這就類似我們平時手機訂火車票和電影票。

2.降低系統耦合性

我們知道模塊分散式部署以後聚合方式通常有兩種:1.分散式消息隊列和2.分散式服務

先來簡單說一下分散式服務:

目前使用比較多的用來構建SOA(Service Oriented Architecture面向服務體系結構)分散式服務框架是阿里巴巴開源的Dubbo.如果想深入了解Dubbo的可以看我寫的關於Dubbo的這一篇文章:《高性能優秀的服務框架-dubbo介紹》juejin.im/post/5acadeb1

再來談我們的分散式消息隊列:

我們知道如果模塊之間不存在直接調用,那麼新增模塊或者修改模塊就對其他模塊影響較小,這樣系統的可擴展性無疑更好一些。

我們最常見的事件驅動架構類似生產者消費者模式,在大型網站中通常用利用消息隊列實現事件驅動結構。如下圖所示:

消息隊列使利用發布-訂閱模式工作,消息發送者(生產者)發布消息,一個或多個消息接受者(消費者)訂閱消息。 從上圖可以看到消息發送者(生產者)和消息接受者(消費者)之間沒有直接耦合,消息發送者將消息發送至分散式消息隊列即結束對消息的處理,消息接受者從分散式消息隊列獲取該消息後進行後續處理,並不需要知道該消息從何而來。對新增業務,只要對該類消息感興趣,即可訂閱該消息,對原有系統和業務沒有任何影響,從而實現網站業務的可擴展性設計

消息接受者對消息進行過濾、處理、包裝後,構造成一個新的消息類型,將消息繼續發送出去,等待其他消息接受者訂閱該消息。因此基於事件(消息對象)驅動的業務架構可以是一系列流程。

另外為了避免消息隊列伺服器宕機造成消息丟失,會將成功發送到消息隊列的消息存儲在消息生產者伺服器上,等消息真正被消費者伺服器處理後才刪除消息。在消息隊列伺服器宕機後,生產者伺服器會選擇分散式消息隊列伺服器集群中的其他伺服器發布消息。

備註: 不要認為消息隊列只能利用發布-訂閱模式工作,只不過在解耦這個特定業務環境下是使用發布-訂閱模式的,比如在我們的ActiveMQ消息隊列中還有點對點工作模式,具體的會在後面的文章給大家詳細介紹,這一篇文章主要還是讓大家對消息隊列有一個更透徹的了解。

常見的消息隊列介紹

1.ActiveMQ

官網:activemq.apache.org/

簡介:

ActiveMQ 是Apache出品,最流行的,能力強勁的開源消息匯流排。ActiveMQ 是一個完全支持JMS1.1和J2EE 1.4規範的 JMS Provider實現,儘管JMS規範出台已經是很久的事情了,但是JMS在當今的J2EE應用中間仍然扮演著特殊的地位。

特點:

  1. 支持來自Java,C,C ++,C#,Ruby,Perl,Python,PHP的各種跨語言客戶端和協議
  2. 完全支持JMS客戶端和Message Broker中的企業集成模式
  3. 支持許多高級功能,如消息組,虛擬目標,通配符和複合目標
  4. 完全支持JMS 1.1和J2EE 1.4,支持瞬態,持久,事務和XA消息
  5. Spring支持,以便ActiveMQ可以輕鬆嵌入到Spring應用程序中,並使用Spring的XML配置機制進行配置
  6. 專為高性能集群,客戶端 - 伺服器,基於對等的通信而設計
  7. CXF和Axis支持,以便ActiveMQ可以輕鬆地放入這些Web服務堆棧中以提供可靠的消息傳遞
  8. 可以用作內存JMS提供程序,非常適合單元測試JMS
  9. 支持可插拔傳輸協議,例如in-VM,TCP,SSL,NIO,UDP,多播,JGroups和JXTA傳輸
  10. 使用JDBC和高性能日誌支持非常快速的持久性

2.RabbitMQ

官網:rabbitmq.com/

簡介:

RabbitMQ 是一個由 Erlang 語言開發的 AMQP 的開源實現。RabbitMQ輕巧且易於部署在雲端。 它支持多種消息傳遞協議。 RabbitMQ可以部署在分散式和聯合配置中,以滿足高規模,高可用性需求。RabbitMQ可運行在許多操作系統和雲環境中,並為大多數流行語言提供廣泛的開發工具。(來自官網翻譯)

AMQP (Advanced MessageQueue):高級消息隊列協議。它是應用層協議的一個開放標準,為面向消息的中間件設計,基於此協議的客戶端與消息中間件可傳遞消息,並不受產品、開發語言等條件的限制。

RabbitMQ最初廣泛應用於金融行業,根據官網描述,它具有如下特點:

特點:

1. 非同步消息傳遞:支持多種消息協議,消息隊列,傳送確認,靈活的路由到隊列,多種交換類型;

2. 支持幾乎所有最受歡迎的編程語言:Java,C,C ++,C#,Ruby,Perl,Python,PHP等等;

3. 可以部署為高可用性和吞吐量的集群; 跨多個可用區域和區域進行聯合;

4. 可插入的身份驗證,授權,支持TLS和LDAP。;

5. 提供了一個易用的用戶界面,使得用戶可以監控和管理消息 Broker 的許多方面;

6. 提供了許多插件,來從多方面進行擴展,也可以編寫自己的插件。

3. Kafka

官網:kafka.apache.org/

簡介:

Kafka是由Apache軟體基金會開發的一個開源流處理平台,由Scala和Java編寫。Kafka是一種高吞吐量的分散式發布訂閱消息系統,它可以處理消費者規模的網站中的所有動作流數據。 這種動作(網頁瀏覽,搜索和其他用戶的行動)是在現代網路上的許多社會功能的一個關鍵因素。 這些數據通常是由於吞吐量的要求而通過處理日誌和日誌聚合來解決。 對於像Hadoop的一樣的日誌數據和離線分析系統,但又要求實時處理的限制,這是一個可行的解決方案。Kafka的目的是通過Hadoop的並行載入機制來統一線上和離線的消息處理,也是為了通過集群來提供實時的消息。

Kafka它主要用於處理活躍的流式數據,因此Kafaka在大數據系統中使用較多。

特點:

1. 同時為發布和訂閱提供高吞吐量。據了解,Kafka每秒可以生產約25萬消息(50 MB),每秒處理55萬消息(110 MB)。

2. 可進行持久化操作。將消息持久化到磁碟,因此可用於批量消費,例如ETL,以及實時應用程序。通過將數據持久化到硬碟以及replication防止數據丟失。

3. 分散式系統,易於向外擴展。所有的producer、broker和consumer都會有多個,均為分散式的。無需停機即可擴展機器。

4. 消息被處理的狀態是在consumer端維護,而不是由server端維護。當失敗時能自動平衡。

5. 支持online和offline的場景。

4. RocketMQ

官網:rocketmq.apache.org/

簡介:

RocketMQ是阿里開源的消息中間件,目前在Apache孵化,使用純Java開發,具有高吞吐量、高可用性、適合大規模分散式系統應用的特點。RocketMQ思路起源於Kafka,但並不是簡單的複製,它對消息的可靠傳輸及事務性做了優化,目前在阿里集團被廣泛應用於交易、充值、流計算、消息推送、日誌流式處理、binglog分發等場景,支撐了阿里多次雙十一活動。

特點:

1. 支持發布/訂閱(Pub/Sub)和點對點(P2P)消息模型

2. 在一個隊列中可靠的先進先出(FIFO)和嚴格的順序傳遞

3. 支持拉(pull)和推(push)兩種消息模式

4. 單一隊列百萬消息的堆積能力

5. 支持多種消息協議,如 JMS、MQTT 等

6. 分散式高可用的部署架構,滿足至少一次消息傳遞語義

7. 提供 docker 鏡像用於隔離測試和雲集群部署

8. 提供配置、指標和監控等功能豐富的 Dashboard

區別(圖片來源慕課網):

其實對於這些消息隊列的產品,每一種都在某一領域佔有一席,雖然ActiveMQ目前在社區已經不是很活躍,但是其下一代產品Apollo已經問世。ZeroMQ小而美,RabbitMQ大而穩,Kakfa和RocketMQ快而強勁。RocketMQ雖然目前還很多不完善,但是一旦在Apache孵化成為頂級項目,全球程序猿開始貢獻,前途也是不可限量的。

下一篇文章我會詳細介紹ActiveMQ以及相關使用方法。

歡迎關注我的微信公眾號:"Java面試通關手冊"(一個有溫度的微信公眾號,期待與你共同進步~~~堅持原創,分享美文,分享各種Java學習資源):

weixin.qq.com/r/2C49JXz (二維碼自動識別)


推薦閱讀:

消息隊列的使用場景
調用:RPC MQ
螞蟻消息中間件 (MsgBroker) 在 YGC 優化上的探索
消息隊列的冪等性
Spring 整合JMS 基於ActiveMQ 實現消息的發送接收

TAG:RabbitMQ | Redis | 消息隊列 |