1. 程式人生 > >常見消息隊列介紹以及比較總結

常見消息隊列介紹以及比較總結

授權 loki 好的 基於 man 性能 ssl erl work

導語 : 消息隊列是分布式系統中重要的組件,在很多生產環境如商品搶購等需要控制並發量的場景下都需要用到。最近組內需要做流水server的選型升級,這裏對消息隊列及常見的消息隊列進行了一次調研,整理了相關資料,分享給大家。


一、消息隊列(MQ)概述


消息隊列(Message Queue),是分布式系統中重要的組件,其通用的使用場景可以簡單地描述為:


當不需要立即獲得結果,但是並發量又需要進行控制的時候,差不多就是需要使用消息隊列的時候。

消息隊列主要解決了應用耦合、異步處理、流量削鋒等問題。


當前使用較多的消息隊列有RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ、MetaMq等,而部分數據庫如Redis、Mysql以及phxsql也可實現消息隊列的功能。


二、消息隊列使用場景


消息隊列在實際應用中包括如下四個場景:


  • 應用耦合:多應用間通過消息隊列對同一消息進行處理,避免調用接口失敗導致整個過程失敗;

  • 異步處理:多應用對消息隊列中同一消息進行處理,應用間並發處理消息,相比串行處理,減少處理時間;

  • 限流削峰:廣泛應用於秒殺或搶購活動中,避免流量過大導致應用系統掛掉的情況;

  • 消息驅動的系統:系統分為消息隊列、消息生產者、消息消費者,生產者負責產生消息,消費者(可能有多個)負責對消息進行處理;


下面詳細介紹上述四個場景以及消息隊列如何在上述四個場景中使用:


2.1 異步處理


具體場景:用戶為了使用某個應用,進行註冊,系統需要發送註冊郵件並驗證短信。對這兩個操作的處理方式有兩種:串行及並行。


(1)串行方式:新註冊信息生成後,先發送註冊郵件,再發送驗證短信;


技術分享圖片

在這種方式下,需要最終發送驗證短信後再返回給客戶端。


(2)並行處理:新註冊信息寫入後,由發短信和發郵件並行處理;


技術分享圖片

在這種方式下,發短信和發郵件 需處理完成後再返回給客戶端。


假設以上三個子系統處理的時間均為50ms,且不考慮網絡延遲,則總的處理時間:


串行:50+50+50=150ms 並行:50+50 = 100ms

若使用消息隊列:


技術分享圖片

並在寫入消息隊列後立即返回成功給客戶端,則總的響應時間依賴於寫入消息隊列的時間,而寫入消息隊列的時間本身是可以很快的,基本可以忽略不計,因此總的處理時間相比串行提高了2倍,相比並行提高了一倍;


2.2 應用耦合


具體場景:用戶使用QQ相冊上傳一張圖片,人臉識別系統會對該圖片進行人臉識別,一般的做法是,服務器接收到圖片後,圖片上傳系統立即調用人臉識別系統,調用完成後再返回成功,如下圖所示:


技術分享圖片

該方法有如下缺點:


  • 人臉識別系統被調失敗,導致圖片上傳失敗;

  • 延遲高,需要人臉識別系統處理完成後,再返回給客戶端,即使用戶並不需要立即知道結果;

  • 圖片上傳系統與人臉識別系統之間互相調用,需要做耦合;


若使用消息隊列:


技術分享圖片

客戶端上傳圖片後,圖片上傳系統將圖片信息如uin、批次寫入消息隊列,直接返回成功;而人臉識別系統則定時從消息隊列中取數據,完成對新增圖片的識別。

此時圖片上傳系統並不需要關心人臉識別系統是否對這些圖片信息的處理、以及何時對這些圖片信息進行處理。事實上,由於用戶並不需要立即知道人臉識別結果,人臉識別系統可以選擇不同的調度策略,按照閑時、忙時、正常時間,對隊列中的圖片信息進行處理。


2.3 限流削峰


具體場景:購物網站開展秒殺活動,一般由於瞬時訪問量過大,服務器接收過大,會導致流量暴增,相關系統無法處理請求甚至崩潰。而加入消息隊列後,系統可以從消息隊列中取數據,相當於消息隊列做了一次緩沖。


技術分享圖片

該方法有如下優點:


  1. 請求先入消息隊列,而不是由業務處理系統直接處理,做了一次緩沖,極大地減少了業務處理系統的壓力;

  2. 隊列長度可以做限制,事實上,秒殺時,後入隊列的用戶無法秒殺到商品,這些請求可以直接被拋棄,返回活動已結束或商品已售完信息;


2.4 消息驅動的系統


具體場景:用戶新上傳了一批照片, 人臉識別系統需要對這個用戶的所有照片進行聚類,聚類完成後由對賬系統重新生成用戶的人臉索引(加快查詢)。這三個子系統間由消息隊列連接起來,前一個階段的處理結果放入隊列中,後一個階段從隊列中獲取消息繼續處理。


技術分享圖片

該方法有如下優點:


  • 避免了直接調用下一個系統導致當前系統失敗;

  • 每個子系統對於消息的處理方式可以更為靈活,可以選擇收到消息時就處理,可以選擇定時處理,也可以劃分時間段按不同處理速度處理;


三、消息隊列的兩種模式


消息隊列包括兩種模式,點對點模式(point to point, queue)和發布/訂閱模式(publish/subscribe,topic)。


3.1 點對點模式


點對點模式下包括三個角色:


  • 消息隊列

  • 發送者 (生產者)

  • 接收者(消費者)


技術分享圖片

消息發送者生產消息發送到queue中,然後消息接收者從queue中取出並且消費消息。消息被消費以後,queue中不再有存儲,所以消息接收者不可能消費到已經被消費的消息。


點對點模式特點:


  • 每個消息只有一個接收者(Consumer)(即一旦被消費,消息就不再在消息隊列中);

  • 發送者和接收者間沒有依賴性,發送者發送消息之後,不管有沒有接收者在運行,都不會影響到發送者下次發送消息;

  • 接收者在成功接收消息之後需向隊列應答成功,以便消息隊列刪除當前接收的消息;


3.2 發布/訂閱模式


發布/訂閱模式下包括三個角色:


  • 角色主題(Topic)

  • 發布者(Publisher)

  • 訂閱者(Subscriber)


技術分享圖片

發布者將消息發送到Topic,系統將這些消息傳遞給多個訂閱者。


發布/訂閱模式特點:


  • 每個消息可以有多個訂閱者;

  • 發布者和訂閱者之間有時間上的依賴性。針對某個主題(Topic)的訂閱者,它必須創建一個訂閱者之後,才能消費發布者的消息。

  • 為了消費消息,訂閱者需要提前訂閱該角色主題,並保持在線運行;


四、常用消息隊列介紹


本部分主要介紹四種常用的消息隊列(RabbitMQ/ActiveMQ/RocketMQ/Kafka)的主要特性、優點、缺點。


4.1 RabbitMQ


RabbitMQ 2007年發布,是一個在AMQP(高級消息隊列協議)基礎上完成的,可復用的企業消息系統,是當前最主流的消息中間件之一。


主要特性:


  1. 可靠性: 提供了多種技術可以讓你在性能和可靠性之間進行權衡。這些技術包括持久性機制、投遞確認、發布者證實和高可用性機制;

  2. 靈活的路由: 消息在到達隊列前是通過交換機進行路由的。RabbitMQ為典型的路由邏輯提供了多種內置交換機類型。如果你有更復雜的路由需求,可以將這些交換機組合起來使用,你甚至可以實現自己的交換機類型,並且當做RabbitMQ的插件來使用;

  3. 消息集群:在相同局域網中的多個RabbitMQ服務器可以聚合在一起,作為一個獨立的邏輯代理來使用;

  4. 隊列高可用:隊列可以在集群中的機器上進行鏡像,以確保在硬件問題下還保證消息安全;

  5. 多種協議的支持:支持多種消息隊列協議;

  6. 服務器端用Erlang語言編寫,支持只要是你能想到的所有編程語言;

  7. 管理界面: RabbitMQ有一個易用的用戶界面,使得用戶可以監控和管理消息Broker的許多方面;

  8. 跟蹤機制:如果消息異常,RabbitMQ提供消息跟蹤機制,使用者可以找出發生了什麽;

  9. 插件機制:提供了許多插件,來從多方面進行擴展,也可以編寫自己的插件;


使用RabbitMQ需要:


  • ErLang語言包

  • RabbitMQ安裝包


RabbitMQ可以運行在Erlang語言所支持的平臺之上:


Solaris

BSD

Linux

MacOSX

TRU64

Windows NT/2000/XP/Vista/Windows 7/Windows 8

Windows Server 2003/2008/2012

Windows 95, 98

VxWorks


優點:


  1. 由於erlang語言的特性,mq 性能較好,高並發;

  2. 健壯、穩定、易用、跨平臺、支持多種語言、文檔齊全;

  3. 有消息確認機制和持久化機制,可靠性高;

  4. 高度可定制的路由;

  5. 管理界面較豐富,在互聯網公司也有較大規模的應用;

  6. 社區活躍度高;


缺點:


  1. 盡管結合erlang語言本身的並發優勢,性能較好,但是不利於做二次開發和維護;

  2. 實現了代理架構,意味著消息在發送到客戶端之前可以在中央節點上排隊。此特性使得RabbitMQ易於使用和部署,但是使得其運行速度較慢,因為中央節點增加了延遲,消息封裝後也比較大;

  3. 需要學習比較復雜的接口和協議,學習和維護成本較高;


4.2 ActiveMQ


ActiveMQ是由Apache出品,ActiveMQ 是一個完全支持JMS1.1和J2EE 1.4規範的 JMS Provider實現。它非常快速,支持多種語言的客戶端和協議,而且可以非常容易的嵌入到企業的應用環境中,並有許多高級功能。


主要特性:


  1. 服從 JMS 規範:JMS 規範提供了良好的標準和保證,包括:同步或異步的消息分發,一次和僅一次的消息分發,消息接收和訂閱等等。遵從 JMS 規範的好處在於,不論使用什麽 JMS 實現提供者,這些基礎特性都是可用的;

  2. 連接性:ActiveMQ 提供了廣泛的連接選項,支持的協議有:HTTP/S,IP 多播,SSL,STOMP,TCP,UDP,XMPP等等。對眾多協議的支持讓 ActiveMQ 擁有了很好的靈活性。

  3. 支持的協議種類多:OpenWire、STOMP、REST、XMPP、AMQP ;

  4. 持久化插件和安全插件:ActiveMQ 提供了多種持久化選擇。而且,ActiveMQ 的安全性也可以完全依據用戶需求進行自定義鑒權和授權;

  5. 支持的客戶端語言種類多:除了 Java 之外,還有:C/C++,.NET,Perl,PHP,Python,Ruby;

  6. 代理集群:多個 ActiveMQ 代理可以組成一個集群來提供服務;

  7. 異常簡單的管理:ActiveMQ 是以開發者思維被設計的。所以,它並不需要專門的管理員,因為它提供了簡單又使用的管理特性。有很多中方法可以監控 ActiveMQ 不同層面的數據,包括使用在 JConsole 或者 ActiveMQ 的Web Console 中使用 JMX,通過處理 JMX 的告警消息,通過使用命令行腳本,甚至可以通過監控各種類型的日誌。


使用ActiveMQ需要:


  • Java JDK

  • ActiveMQ安裝包


ActiveMQ可以運行在Java語言所支持的平臺之上。


優點:


  1. 跨平臺(JAVA編寫與平臺無關有,ActiveMQ幾乎可以運行在任何的JVM上)

  2. 可以用JDBC:可以將數據持久化到數據庫。雖然使用JDBC會降低ActiveMQ的性能,但是數據庫一直都是開發人員最熟悉的存儲介質。將消息存到數據庫,看得見摸得著。而且公司有專門的DBA去對數據庫進行調優,主從分離;

  3. 支持JMS :支持JMS的統一接口;

  4. 支持自動重連;

  5. 有安全機制:支持基於shiro,jaas等多種安全配置機制,可以對Queue/Topic進行認證和授權。

  6. 監控完善:擁有完善的監控,包括Web Console,JMX,Shell命令行,Jolokia的REST API;

  7. 界面友善:提供的Web Console可以滿足大部分情況,還有很多第三方的組件可以使用,如hawtio;

缺點:


  1. 社區活躍度不及RabbitMQ高;

  2. 根據其他用戶反饋,會出莫名其妙的問題,會丟失消息;

  3. 目前重心放到activemq6.0產品-apollo,對5.x的維護較少;

  4. 不適合用於上千個隊列的應用場景;


4.3 RocketMQ


RocketMQ出自 阿裏公司的開源產品,用 Java 語言實現,在設計時參考了 Kafka,並做出了自己的一些改進,消息可靠性上比 Kafka 更好。RocketMQ在阿裏集團被廣泛應用在訂單,交易,充值,流計算,消息推送,日誌流式處理,binglog分發等場景。


主要特性:


  1. 是一個隊列模型的消息中間件,具有高性能、高可靠、高實時、分布式特點;

  2. Producer、Consumer、隊列都可以分布式;

  3. Producer向一些隊列輪流發送消息,隊列集合稱為Topic,Consumer如果做廣播消費,則一個consumer實例消費這個Topic對應的所有隊列,如果做集群消費,則多個Consumer實例平均消費這個topic對應的隊列集合;

  4. 能夠保證嚴格的消息順序;

  5. 提供豐富的消息拉取模式;

  6. 高效的訂閱者水平擴展能力;

  7. 實時的消息訂閱機制;

  8. 億級消息堆積能力;

  9. 較少的依賴;


使用RocketMQ需要:


  • Java JDK

  • 安裝git、Maven

  • RocketMQ安裝包


RocketMQ可以運行在Java語言所支持的平臺之上。


優點:


  1. 單機支持 1 萬以上持久化隊列

  2. RocketMQ 的所有消息都是持久化的,先寫入系統 PAGECACHE,然後刷盤,可以保證內存與磁盤都有一份數據,

訪問時,直接從內存讀取。

  1. 模型簡單,接口易用(JMS 的接口很多場合並不太實用);

  2. 性能非常好,可以大量堆積消息在broker中;

  3. 支持多種消費,包括集群消費、廣播消費等。

  4. 各個環節分布式擴展設計,主從HA;

  5. 開發度較活躍,版本更新很快。


缺點:


支持的客戶端語言不多,目前是java及c++,其中c++不成熟;

RocketMQ社區關註度及成熟度也不及前兩者;

沒有web管理界面,提供了一個CLI(命令行界面)管理工具帶來查詢、管理和診斷各種問題;

沒有在 mq 核心中去實現JMS等接口;


4.4 Kafka


Apache Kafka是一個分布式消息發布訂閱系統。它最初由LinkedIn公司基於獨特的設計實現為一個分布式的提交日誌系統( a distributed commit log),,之後成為Apache項目的一部分。Kafka系統快速、可擴展並且可持久化。它的分區特性,可復制和可容錯都是其不錯的特性。


主要特性:


  1. 快速持久化,可以在O(1)的系統開銷下進行消息持久化;

  2. 高吞吐,在一臺普通的服務器上既可以達到10W/s的吞吐速率;

  3. .完全的分布式系統,Broker、Producer、Consumer都原生自動支持分布式,自動實現負載均衡;

  4. 支持同步和異步復制兩種HA;

  5. 支持數據批量發送和拉取;

  6. zero-copy:減少IO操作步驟;

  7. 數據遷移、擴容對用戶透明;

  8. 無需停機即可擴展機器;

  9. 其他特性:嚴格的消息順序、豐富的消息拉取模型、高效訂閱者水平擴展、實時的消息訂閱、億級的消息堆積能力、定期刪除機制;


使用Kafka需要:


  • Java JDK

  • Kafka安裝包


優點:


  1. 客戶端語言豐富,支持java、.net、php、ruby、python、go等多種語言;

  2. 性能卓越,單機寫入TPS約在百萬條/秒,消息大小10個字節;

  3. 提供完全分布式架構, 並有replica機制, 擁有較高的可用性和可靠性, 理論上支持消息無限堆積;

  4. 支持批量操作;

  5. 消費者采用Pull方式獲取消息, 消息有序, 通過控制能夠保證所有消息被消費且僅被消費一次;

  6. 有優秀的第三方Kafka Web管理界面Kafka-Manager;

  7. 在日誌領域比較成熟,被多家公司和多個開源項目使用;


缺點:


  1. Kafka單機超過64個隊列/分區,Load會發生明顯的飆高現象,隊列越多,load越高,發送消息響應時間變長

  2. 使用短輪詢方式,實時性取決於輪詢間隔時間;

  3. 消費失敗不支持重試;

  4. 支持消息順序,但是一臺代理宕機後,就會產生消息亂序;

  5. 社區更新較慢;


4.5 RabbitMQ/ActiveMQ/RocketMQ/Kafka對比


這裏列舉了上述四種消息隊列的差異對比:


技術分享圖片

結論:


Kafka在於分布式架構,RabbitMQ基於AMQP協議來實現,RocketMQ/思路來源於kafka,改成了主從結構,在事務性可靠性方面做了優化。廣泛來說,電商、金融等對事務性要求很高的,可以考慮RabbitMQ和RocketMQ,對性能要求高的可考慮Kafka。


五、參考資料:


5.1 消息隊列:


  1. 大型網站架構之分布式消息隊列 http://blog.csdn.net/shaobingj126/article/details/50585035

  2. 消息隊列的使用場景 https://www.zhihu.com/question/34243607/answer/127666030

  3. 淺談異步消息隊列模型 http://www.cnblogs.com/sunkeydev/p/5248855.html

  4. 消息隊列的兩種模式 http://blog.csdn.net/heyutao007/article/details/50131089


5.2 RabbitMQ


  1. RabbitMQ主頁 https://www.rabbitmq.com/

  2. RabbitMQ學習教程 https://www.rabbitmq.com/getstarted.html

  3. 專欄:RabbitMQ從入門到精通 http://blog.csdn.net/column/details/rabbitmq.html

  4. RabbitMQ能為你做些什麽 http://rabbitmq.mr-ping.com/description.html

  5. RabbitMQ指南(1)-特性及功能 https://blog.zenfery.cc/archives/79.html


5.3 ActiveMQ

  1. ActiveMQ主頁 http://activemq.apache.org/

  2. Apache ActiveMQ介紹 http://jfires.iteye.com/blog/1187688

  3. ActiveMQ的簡介與安裝 http://blog.csdn.net/sl1992/article/details/72824562

  4. ActiveMQ 和消息簡介 http://www.cnblogs.com/craftsman-gao/p/7002605.html


5.4 RocketMQ

  1. 主頁 https://github.com/alibaba/RocketMQ

  2. RocketMQ 原理簡介 http://alibaba.github.io/RocketMQ-docs/document/design/RocketMQ_design.pdf

  3. RocketMQ與kafka對比(18項差異) http://jm.taobao.org/2016/03/24/rmq-vs-kafka/



5.5 Kafka

1.Kafka主頁: http://kafka.apache.org/

  1. Kafka特性 http://www.cnblogs.com/lsx1993/p/4847719.html

  2. Kafka客戶端支持語言 https://cwiki.apache.org/confluence/display/KAFKA/Clients


5.6 RabbitMQ/ActiveMQ/RocketMQ/Kafka對比

  1. RocketMQ,隊列選型 http://www.zmannotes.com/index.php/2016/01/17/rocketmq/

  2. RabbitMQ和Kafka http://www.dongcoder.com/detail-416804.html

  3. 即時通信RabbitMQ二-性能測試 http://www.jianshu.com/p/d31ae9e3bfb6

  4. RabbitMq、ActiveMq、ZeroMq、kafka之間的比較,資料匯總 http://blog.csdn.net/linsongbin1/article/details/47781187

  5. 消息隊列軟件產品大比拼 http://www.cnblogs.com/amityat/archive/2011/08/31/2160293.html


總結:


消息隊列利用高效可靠的消息傳遞機制進行平臺無關的數據交流,並基於數據通信來進行分布式系統的集成。目前業界有很多的MQ產品,例如RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ、MetaMq等,也有直接使用數據庫redis充當消息隊列的案例。而這些消息隊列產品,各有側重,在實際選型時,需要結合自身需求及MQ產品特征,綜合考慮。


常見消息隊列介紹以及比較總結