【MQ】消息隊列及常見MQ比較

来源:https://www.cnblogs.com/weknow619/archive/2019/04/26/10730835.html
-Advertisement-
Play Games

一、什麼是消息隊列 我們可以把消息隊列比作是一個存放消息的容器,當我們需要使用消息的時候可以取出消息供自己使用。消息隊列是分散式系統中重要的組件,使用消息隊列主要是為了通過非同步處理提高系統性能和削峰、降低系統耦合性。目前使用較多的消息隊列有ActiveMQ,RabbitMQ,Kafka,Rocket ...


一、什麼是消息隊列

  我們可以把消息隊列比作是一個存放消息的容器,當我們需要使用消息的時候可以取出消息供自己使用。消息隊列是分散式系統中重要的組件,使用消息隊列主要是為了通過非同步處理提高系統性能和削峰降低系統耦合性。目前使用較多的消息隊列有ActiveMQ,RabbitMQ,Kafka,RocketMQ,我們後面會一一對比這些消息隊列。

  另外,我們知道隊列 Queue 是一種先進先出的數據結構,所以消費消息時也是按照順序來消費的。比如生產者發送消息1,2,3...對於消費者就會按照1,2,3...的順序來消費。但是偶爾也會出現消息被消費的順序不對的情況,比如某個消息消費失敗又或者一個 queue 多個consumer 也會導致消息被消費的順序不對,我們一定要保證消息被消費的順序正確。

  除了上面說的消息消費順序的問題,使用消息隊列,我們還要考慮如何保證消息不被重覆消費?如何保證消息的可靠性傳輸(如何處理消息丟失的問題)?......等等問題。所以說使用消息隊列也不是十全十美的,使用它也會讓系統可用性降低複雜度提高,另外需要我們保障一致性等問題。

 

二、為什麼要用消息隊列

  我覺得使用消息隊列主要有兩點好處:1.通過非同步處理提高系統性能(削峰、減少響應所需時間);2.降低系統耦合性。如果在面試的時候你被面試官問到這個問題的話,一般情況是你在你的簡歷上涉及到消息隊列這方面的內容,這個時候推薦你結合你自己的項目來回答。

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

2.1通過非同步處理提高系統性能(削峰、減少響應所需時間)

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

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

 

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

2.2降低系統耦合性

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

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

 

消息隊列使利用發佈-訂閱模式工作,消息發送者(生產者)發佈消息,一個或多個消息接受者(消費者)訂閱消息。 

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

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

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

備註: 不要認為消息隊列只能利用發佈-訂閱模式工作,只不過在解耦這個特定業務環境下是使用發佈-訂閱模式的。除了發佈-訂閱模式,還有點對點訂閱模式(一個消息只有一個消費者),我們比較常用的是發佈-訂閱模式。 另外,這兩種消息模型是 JMS 提供的,AMQP 協議還提供了 5 種消息模型。

 

三、使用消息隊列帶來的一些問題

  • 系統可用性降低: 系統可用性在某種程度上降低,為什麼這樣說呢?在加入MQ之前,你不用考慮消息丟失或者說MQ掛掉等等的情況,但是,引入MQ之後你就需要去考慮了!
  • 系統複雜性提高: 加入MQ之後,你需要保證消息沒有被重覆消費、處理消息丟失的情況、保證消息傳遞的順序性等等問題!
  • 一致性問題: 我上面講了消息隊列可以實現非同步,消息隊列帶來的非同步確實可以提高系統響應速度。但是,萬一消息的真正消費者並沒有正確消費消息怎麼辦?這樣就會導致數據不一致的情況了!

四、JMS VS AMQP

4.1 JMS

4.1.1 JMS 簡介

JMS(JAVA Message Service,java消息服務)是java的消息服務,JMS的客戶端之間可以通過JMS服務進行非同步的消息傳輸。JMS(JAVA Message Service,Java消息服務)API是一個消息服務的標準或者說是規範,允許應用程式組件基於JavaEE平臺創建、發送、接收和讀取消息。它使分散式通信耦合度更低,消息服務更加可靠以及非同步性。

ActiveMQ 就是基於 JMS 規範實現的。

4.1.2 JMS兩種消息模型

①點到點(P2P)模型

為消息通信載體;滿足生產者與消費者模式,一條消息只能被一個消費者使用,未被消費的消息在隊列中保留直到被消費或超時。比如:我們生產者發送100條消息的話,兩個消費者來消費一般情況下兩個消費者會按照消息發送的順序各自消費一半(也就是你一個我一個的消費。)

② 發佈/訂閱(Pub/Sub)模型

發佈訂閱模型(Pub/Sub) 使用主題(Topic)作為消息通信載體,類似於廣播模式;發佈者發佈一條消息,該消息通過主題傳遞給所有的訂閱者,在一條消息廣播之後才訂閱的用戶則是收不到該條消息的。

4.1.3 JMS 五種不同的消息正文格式

  JMS定義了五種不同的消息正文格式,以及調用的消息類型,允許你發送並接收以一些不同形式的數據,提供現有消息格式的一些級別的相容性。

  • StreamMessage -- Java原始值的數據流
  • MapMessage--一套名稱-值對
  • TextMessage--一個字元串對象
  • ObjectMessage--一個序列化的 Java對象
  • BytesMessage--一個位元組的數據流

4.2 AMQP

  ​ AMQP,即Advanced Message Queuing Protocol,一個提供統一消息服務的應用層標準 高級消息隊列協議(二進位應用層協議),是應用層協議的一個開放標準,為面向消息的中間件設計,相容 JMS。基於此協議的客戶端與消息中間件可傳遞消息,並不受客戶端/中間件同產品,不同的開發語言等條件的限制。

RabbitMQ 就是基於 AMQP 協議實現的。

4.3 JMS vs AMQP

對比方向JMSAMQP
定義 Java API 協議
跨語言
跨平臺
支持消息類型 提供兩種消息模型:①Peer-2-Peer;②Pub/sub 提供了五種消息模型:①direct exchange;②fanout exchange;③topic change;④headers exchange;⑤system exchange。本質來講,後四種和JMS的pub/sub模型沒有太大差別,僅是在路由機制上做了更詳細的劃分;
支持消息類型 支持多種消息類型 ,我們在上面提到過 byte[](二進位)

總結:

  • AMQP 為消息定義了線路層(wire-level protocol)的協議,而JMS所定義的是API規範。在 Java 體系中,多個client均可以通過JMS進行交互,不需要應用修改代碼,但是其對跨平臺的支持較差。而AMQP天然具有跨平臺、跨語言特性。
  • JMS 支持TextMessage、MapMessage 等複雜的消息類型;而 AMQP 僅支持 byte[] 消息類型(複雜的類型可序列化後發送)。
  • 由於Exchange 提供的路由演算法,AMQP可以提供多樣化的路由方式來傳遞消息到消息隊列,而 JMS 僅支持 隊列 和 主題/訂閱 方式兩種。

 

五、常見的消息隊列對比

 

對比方向概要
吞吐量 萬級的 ActiveMQ 和 RabbitMQ 的吞吐量(ActiveMQ 的性能最差)要比 十萬級甚至是百萬級的 RocketMQ 和 Kafka 低一個數量級。
可用性 都可以實現高可用。ActiveMQ 和 RabbitMQ 都是基於主從架構實現高可用性。RocketMQ 基於分散式架構。 kafka 也是分散式的,一個數據多個副本,少數機器宕機,不會丟失數據,不會導致不可用
時效性 RabbitMQ 基於erlang開發,所以併發能力很強,性能極其好,延時很低,達到微秒級。其他三個都是 ms 級。
功能支持 除了 Kafka,其他三個功能都較為完備。 Kafka 功能較為簡單,主要支持簡單的MQ功能,在大數據領域的實時計算以及日誌採集被大規模使用,是事實上的標準
消息丟失 ActiveMQ 和 RabbitMQ 丟失的可能性非常低, RocketMQ 和 Kafka 理論上不會丟失。

總結:

  • ActiveMQ 的社區算是比較成熟,但是較目前來說,ActiveMQ 的性能比較差,而且版本迭代很慢,不推薦使用。
  • RabbitMQ 在吞吐量方面雖然稍遜於 Kafka 和 RocketMQ ,但是由於它基於 erlang 開發,所以併發能力很強,性能極其好,延時很低,達到微秒級。但是也因為 RabbitMQ 基於 erlang 開發,所以國內很少有公司有實力做erlang源碼級別的研究和定製。如果業務場景對併發量要求不是太高(十萬級、百萬級),那這四種消息隊列中,RabbitMQ 一定是你的首選。如果是大數據領域的實時計算、日誌採集等場景,用 Kafka 是業內標準的,絕對沒問題,社區活躍度很高,絕對不會黃,何況幾乎是全世界這個領域的事實性規範。
  • RocketMQ 阿裡出品,Java 系開源項目,源代碼我們可以直接閱讀,然後可以定製自己公司的MQ,並且 RocketMQ 有阿裡巴巴的實際業務場景的實戰考驗。RocketMQ 社區活躍度相對較為一般,不過也還可以,文檔相對來說簡單一些,然後介面這塊不是按照標準 JMS 規範走的有些系統要遷移需要修改大量代碼。還有就是阿裡出台的技術,你得做好這個技術萬一被拋棄,社區黃掉的風險,那如果你們公司有技術實力我覺得用RocketMQ 挺好的
  • kafka 的特點其實很明顯,就是僅僅提供較少的核心功能,但是提供超高的吞吐量,ms 級的延遲,極高的可用性以及可靠性,而且分散式可以任意擴展。同時 kafka 最好是支撐較少的 topic 數量即可,保證其超高吞吐量。kafka 唯一的一點劣勢是有可能消息重覆消費,那麼對數據準確性會造成極其輕微的影響,在大數據領域中以及日誌採集中,這點輕微影響可以忽略這個特性天然適合大數據實時計算以及日誌收集。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 定義: 定義了一種一對多的依賴關係,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀態發生變化時,會通知所有觀察者對象,使他們能夠自動更新自己。 結構:(書中圖,侵刪) 一個抽象的觀察者介面,擁有一個更新方法 若幹個具體的觀察者類 一個抽象的subject類,包含一個抽象觀察者的集合,並擁有 ...
  • [TOC] 引入 假設有一個司機, 需要到某個城市, 於是我們給他一輛汽車 如果我們希望給到這個司機的始終是一輛車, 應該怎麼做? (單例) 首先我們不能讓司機自己通過 產生一輛汽車, 而是應該通過調用 類中的某個方法對外提供車.   簡單工廠 下麵考慮, 如果我們不希望只有汽車這種交通工 ...
  • freemarker動態生成word並將生成的word轉為PDF,openoffice轉換word亂碼 ...
  • PriorityBlockingQueue的實現方式? PriorityBlockingQueue是否需要擴容? PriorityBlockingQueue是怎麼控制併發安全的? ...
  • 什麼是編程語言 人與電腦交流的介質 編程是什麼東西 寫出一個一個文件,然後一個文件的集合就是一個程式 為什麼要編程 在電腦上寫一個程式實現某種功能,取代勞動力 電腦的五大組成 我們人類最重要的組成是大腦,大腦中有一個控制器,還有一個運算器 CPU中央處理器 1. 控制器:控製作用 2. 運算器 ...
  • 小程式這三個字想必大家都是耳熟能詳,作為一個互聯網的新人,它在2017-2018年中發光發熱,以往,微博、自媒體公眾號都是營銷的主展場,但如今,陣營卻慢慢發生了變化:向小程式靠近。互聯網的發展趨勢仿佛慢慢有了小程式的一席之地,這個事物仿佛突然又好似在我們生活中存在了很久。 然而還有很多實體店對於小程 ...
  • 為什麼需要容錯限流 複雜分散式系統通常有很多依賴,如果一個應用不能對來自依賴 故障進行隔離,那麼應用本身就處在被拖垮的風險中。在一個高流量的網站中,某個單一後端一旦發生延遲,將會在數秒內導致 所有應用資源被耗盡(一個臭雞蛋影響一籃筐)。 如秒殺、搶購、雙十一等場景,在某一時間點會有爆髮式的網路流量涌 ...
  • Python基礎語法(三) 1. 數值型數據結構 1.1 要點 在之前的博客也有提到,數值型數據結構在這裡就不過多介紹了。在這裡提及一些需要知道的知識點。 int、float、complex、bool都是類,1\3.14\2+3j都對象(即實例)。這也符合Python一切皆對象的原則。 int: 在 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...