天天看點

消息隊列及常見消息隊列介紹

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

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

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

目前使用較多的消息隊列有rabbitmq、rocketmq、activemq、kafka、zeromq、metamq等,而部分資料庫如redis、mysql以及phxsql也可實作消息隊列的功能。

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

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

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

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

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

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

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

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

消息隊列及常見消息隊列介紹

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

(2)并行處理:新注冊資訊寫入後,由發短信和發郵件并行處理;

消息隊列及常見消息隊列介紹

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

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

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

若使用消息隊列:

消息隊列及常見消息隊列介紹

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

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

消息隊列及常見消息隊列介紹

該方法有如下缺點:

人臉識别系統被調失敗,導緻圖檔上傳失敗;

延遲高,需要人臉識别系統處理完成後,再傳回給用戶端,即使使用者并不需要立即知道結果;

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

消息隊列及常見消息隊列介紹

用戶端上傳圖檔後,圖檔上傳系統将圖檔資訊如uin、批次寫入消息隊列,直接傳回成功;而人臉識别系統則定時從消息隊列中取資料,完成對新增圖檔的識别。

此時圖檔上傳系統并不需要關心人臉識别系統是否對這些圖檔資訊的處理、以及何時對這些圖檔資訊進行處理。事實上,由于使用者并不需要立即知道人臉識别結果,人臉識别系統可以選擇不同的排程政策,按照閑時、忙時、正常時間,對隊列中的圖檔資訊進行處理。

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

消息隊列及常見消息隊列介紹

該方法有如下優點:

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

隊列長度可以做限制,事實上,秒殺時,後入隊列的使用者無法秒殺到商品,這些請求可以直接被抛棄,傳回活動已結束或商品已售完資訊;

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

消息隊列及常見消息隊列介紹

避免了直接調用下一個系統導緻目前系統失敗;

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

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

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

消息隊列

發送者 (生産者)

接收者(消費者)

消息隊列及常見消息隊列介紹

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

點對點模式特點:

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

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

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

釋出/訂閱模式下包括三個角色:

角色主題(topic)

釋出者(publisher)

訂閱者(subscriber)

消息隊列及常見消息隊列介紹

釋出者将消息發送到topic,系統将這些消息傳遞給多個訂閱者。

釋出/訂閱模式特點:

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

釋出者和訂閱者之間有時間上的依賴性。針對某個主題(topic)的訂閱者,它必須建立一個訂閱者之後,才能消費釋出者的消息。

為了消費消息,訂閱者需要提前訂閱該角色主題,并保持線上運作;

本部分主要介紹四種常用的消息隊列(rabbitmq/activemq/rocketmq/kafka)的主要特性、優點、缺點。

rabbitmq 2007年釋出,是一個在amqp(進階消息隊列協定)基礎上完成的,可複用的企業消息系統,是目前最主流的消息中間件之一。

主要特性:

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

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

消息叢集:在相同區域網路中的多個rabbitmq伺服器可以聚合在一起,作為一個獨立的邏輯代理來使用;

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

多種協定的支援:支援多種消息隊列協定;

伺服器端用erlang語言編寫,支援隻要是你能想到的所有程式設計語言;

管理界面: rabbitmq有一個易用的使用者界面,使得使用者可以監控和管理消息broker的許多方面;

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

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

使用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

優點:

由于erlang語言的特性,mq 性能較好,高并發;

健壯、穩定、易用、跨平台、支援多種語言、文檔齊全;

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

高度可定制的路由;

管理界面較豐富,在網際網路公司也有較大規模的應用;

社群活躍度高;

缺點:

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

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

需要學習比較複雜的接口和協定,學習和維護成本較高;

activemq是由apache出品,activemq 是一個完全支援jms1.1和j2ee 1.4規範的 jms provider實作。它非常快速,支援多種語言的用戶端和協定,而且可以非常容易的嵌入到企業的應用環境中,并有許多進階功能。

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

連接配接性:activemq 提供了廣泛的連接配接選項,支援的協定有:http/s,ip 多點傳播,ssl,stomp,tcp,udp,xmpp等等。對衆多協定的支援讓 activemq 擁有了很好的靈活性。

支援的協定種類多:openwire、stomp、rest、xmpp、amqp ;

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

支援的用戶端語言種類多:除了 java 之外,還有:c/c++,.net,perl,php,python,ruby;

代理叢集:多個 activemq 代理可以組成一個叢集來提供服務;

異常簡單的管理:activemq 是以開發者思維被設計的。是以,它并不需要專門的管理者,因為它提供了簡單又使用的管理特性。有很多中方法可以監控 activemq 不同層面的資料,包括使用在 jconsole 或者 activemq 的web console 中使用 jmx,通過處理 jmx 的告警消息,通過使用指令行腳本,甚至可以通過監控各種類型的日志。

使用activemq需要:

java jdk

activemq安裝包

activemq可以運作在java語言所支援的平台之上。

跨平台(java編寫與平台無關有,activemq幾乎可以運作在任何的jvm上)

可以用jdbc:可以将資料持久化到資料庫。雖然使用jdbc會降低activemq的性能,但是資料庫一直都是開發人員最熟悉的存儲媒體。将消息存到資料庫,看得見摸得着。而且公司有專門的dba去對資料庫進行調優,主從分離;

支援jms :支援jms的統一接口;

支援自動重連;

有安全機制:支援基于shiro,jaas等多種安全配置機制,可以對queue/topic進行認證和授權。

監控完善:擁有完善的監控,包括web console,jmx,shell指令行,jolokia的rest api;

界面友善:提供的web console可以滿足大部分情況,還有很多第三方的元件可以使用,如hawtio;

社群活躍度不及rabbitmq高;

根據其他使用者回報,會出莫名其妙的問題,會丢失消息;

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

不适合用于上千個隊列的應用場景;

rocketmq出自 阿裡公司的開源産品,用 java 語言實作,在設計時參考了 kafka,并做出了自己的一些改進,消息可靠性上比 kafka 更好。rocketmq在阿裡集團被廣泛應用在訂單,交易,充值,流計算,消息推送,日志流式處理,binglog分發等場景。

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

producer、consumer、隊列都可以分布式;

producer向一些隊列輪流發送消息,隊列集合稱為topic,consumer如果做廣播消費,則一個consumer執行個體消費這個topic對應的所有隊列,如果做叢集消費,則多個consumer執行個體平均消費這個topic對應的隊列集合;

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

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

高效的訂閱者水準擴充能力;

實時的消息訂閱機制;

億級消息堆積能力;

較少的依賴;

使用rocketmq需要:

安裝git、maven

rocketmq安裝包

rocketmq可以運作在java語言所支援的平台之上。

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

rocketmq 的所有消息都是持久化的,先寫入系統 pagecache,然後刷盤,可以保證記憶體與磁盤都有一份資料,

通路時,直接從記憶體讀取。

模型簡單,接口易用(jms 的接口很多場合并不太實用);

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

支援多種消費,包括叢集消費、廣播消費等。

各個環節分布式擴充設計,主從ha;

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

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

rocketmq社群關注度及成熟度也不及前兩者;

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

沒有在 mq 核心中去實作jms等接口;

apache kafka是一個分布式消息釋出訂閱系統。它最初由linkedin公司基于獨特的設計實作為一個分布式的送出日志系統( a distributed commit log),,之後成為apache項目的一部分。kafka系統快速、可擴充并且可持久化。它的分區特性,可複制和可容錯都是其不錯的特性。

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

高吞吐,在一台普通的伺服器上既可以達到10w/s的吞吐速率;

.完全的分布式系統,broker、producer、consumer都原生自動支援分布式,自動實作負載均衡;

支援同步和異步複制兩種ha;

支援資料批量發送和拉取;

zero-copy:減少io操作步驟;

資料遷移、擴容對使用者透明;

無需停機即可擴充機器;

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

使用kafka需要:

kafka安裝包

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

性能卓越,單機寫入tps約在百萬條/秒,消息大小10個位元組;

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

支援批量操作;

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

有優秀的第三方kafka web管理界面kafka-manager;

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

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

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

消費失敗不支援重試;

支援消息順序,但是一台代理當機後,就會産生消息亂序;

社群更新較慢;

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

消息隊列及常見消息隊列介紹

結論:

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

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

rabbitmq首頁 https://www.rabbitmq.com/

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

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

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

activemq首頁 http://activemq.apache.org/

apache activemq介紹 http://jfires.iteye.com/blog/1187688

首頁 https://github.com/alibaba/rocketmq

rocketmq 原理簡介 http://alibaba.github.io/rocketmq-docs/document/design/rocketmq_design.pdf

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

1.kafka首頁: http://kafka.apache.org/

kafka用戶端支援語言 https://cwiki.apache.org/confluence/display/kafka/clients

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

rabbitmq和kafka http://www.dongcoder.com/detail-416804.html

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

消息隊列利用高效可靠的消息傳遞機制進行平台無關的資料交流,并基于資料通信來進行分布式系統的內建。目前業界有很多的mq産品,例如rabbitmq、rocketmq、activemq、kafka、zeromq、metamq等,也有直接使用資料庫redis充當消息隊列的案例。而這些消息隊列産品,各有側重,在實際選型時,需要結合自身需求及mq産品特征,綜合考慮。