本文將從腮猖,Kafka鉴扫、RabbitMQ赞枕、ZeroMQ、RocketMQ坪创、ActiveMQ 17 個方面綜合對比作為消息隊列使用時的差異炕婶。
一、資料文檔
Kafka:中莱预。有kafka作者自己寫的書柠掂,網(wǎng)上資料也有一些。rabbitmq:多依沮。有一些不錯的書涯贞,網(wǎng)上資料多。zeromq:少危喉。沒有專門寫zeromq的書宋渔,網(wǎng)上的資料多是一些代碼的實現(xiàn)和簡單介紹。rocketmq:少辜限。沒有專門寫rocketmq的書皇拣,網(wǎng)上的資料良莠不齊,官方文檔很簡潔薄嫡,但是對技術(shù)細節(jié)沒有過多的描述氧急。activemq:多。沒有專門寫activemq的書毫深,網(wǎng)上資料多吩坝。
二、開發(fā)語言
Kafka:Scala rabbitmq:Erlang zeromq:c rocketmq:java activemq:java
三哑蔫、支持的協(xié)議
Kafka:自己定義的一套…(基于TCP) rabbitmq:AMQP zeromq:TCP钉寝、UDP rocketmq:自己定義的一套… activemq:OpenWire手素、STOMP、REST瘩蚪、XMPP泉懦、AMQP
四、消息存儲
Kafka:內(nèi)存疹瘦、磁盤崩哩、數(shù)據(jù)庫。支持大量堆積言沐。
kafka的最小存儲單元是分區(qū)邓嘹,一個topic包含多個分區(qū),kafka創(chuàng)建主題時险胰,這些分區(qū)會被分配在多個服務(wù)器上汹押,通常一個broker一臺服務(wù)器。分區(qū)首領(lǐng)會均勻地分布在不同的服務(wù)器上起便,分區(qū)副本也會均勻的分布在不同的服務(wù)器上棚贾,確保負載均衡和高可用性,當新的broker加入集群的時候榆综,部分副本會被移動到新的broker上妙痹。根據(jù)配置文件中的目錄清單,kafka會把新的分區(qū)分配給目錄清單里分區(qū)數(shù)最少的目錄鼻疮。默認情況下怯伊,分區(qū)器使用輪詢算法把消息均衡地分布在同一個主題的不同分區(qū)中,對于發(fā)送時指定了key的情況判沟,會根據(jù)key的hashcode取模后的值存到對應(yīng)的分區(qū)中耿芹。
rabbitmq:內(nèi)存、磁盤挪哄。支持少量堆積吧秕。
rabbitmq的消息分為持久化的消息和非持久化消息,不管是持久化的消息還是非持久化的消息都可以寫入到磁盤中燥。持久化的消息在到達隊列時就寫入到磁盤寇甸,并且如果可以,持久化的消息也會在內(nèi)存中保存一份備份疗涉,這樣可以提高一定的性能拿霉,當內(nèi)存吃緊的時候會從內(nèi)存中清除。非持久化的消息一般只存在于內(nèi)存中咱扣,在內(nèi)存吃緊的時候會被換入到磁盤中绽淘,以節(jié)省內(nèi)存。
引入鏡像隊列機制闹伪,可將重要隊列“復(fù)制”到集群中的其他broker上沪铭,保證這些隊列的消息不會丟失壮池。配置鏡像的隊列,都包含一個主節(jié)點master和多個從節(jié)點slave,如果master失效杀怠,加入時間最長的slave會被提升為新的master椰憋,除發(fā)送消息外的所有動作都向master發(fā)送,然后由master將命令執(zhí)行結(jié)果廣播給各個slave赔退,rabbitmq會讓master均勻地分布在不同的服務(wù)器上橙依,而同一個隊列的slave也會均勻地分布在不同的服務(wù)器上,保證負載均衡和高可用性硕旗。
zeromq:消息發(fā)送端的內(nèi)存或者磁盤中窗骑。不支持持久化。
rocketmq:磁盤漆枚。支持大量堆積创译。
commitLog文件存放實際的消息數(shù)據(jù),每個commitLog上限是1G墙基,滿了之后會自動新建一個commitLog文件保存數(shù)據(jù)软族。ConsumeQueue隊列只存放offset、size碘橘、tagcode互订,非常小,分布在多個broker上痘拆。ConsumeQueue相當于CommitLog的索引文件,消費者消費時會從consumeQueue中查找消息在commitLog中的offset氮墨,再去commitLog中查找元數(shù)據(jù)纺蛆。
ConsumeQueue存儲格式的特性,保證了寫過程的順序?qū)懕P(寫CommitLog文件)规揪,大量數(shù)據(jù)IO都在順序?qū)懲粋€commitLog桥氏,滿1G了再寫新的。加上rocketmq是累計4K才強制從PageCache中刷到磁盤(緩存)猛铅,所以高并發(fā)寫性能突出字支。
activemq:內(nèi)存、磁盤奸忽、數(shù)據(jù)庫堕伪。支持少量堆積。
五栗菜、消息事務(wù)
Kafka:支持 rabbitmq:支持欠雌。客戶端將信道設(shè)置為事務(wù)模式疙筹,只有當消息被rabbitMq接收富俄,事務(wù)才能提交成功禁炒,否則在捕獲異常后進行回滾。使用事務(wù)會使得性能有所下降 zeromq:不支持 rocketmq:支持 activemq:支持
六霍比、負載均衡
Kafka:支持負載均衡幕袱。
1>一個broker通常就是一臺服務(wù)器節(jié)點。對于同一個Topic的不同分區(qū)悠瞬,Kafka會盡力將這些分區(qū)分布到不同的Broker服務(wù)器上凹蜂,zookeeper保存了broker、主題和分區(qū)的元數(shù)據(jù)信息阁危。分區(qū)首領(lǐng)會處理來自客戶端的生產(chǎn)請求玛痊,kafka分區(qū)首領(lǐng)會被分配到不同的broker服務(wù)器上,讓不同的broker服務(wù)器共同分擔(dān)任務(wù)狂打。
每一個broker都緩存了元數(shù)據(jù)信息,客戶端可以從任意一個broker獲取元數(shù)據(jù)信息并緩存起來趴乡,根據(jù)元數(shù)據(jù)信息知道要往哪里發(fā)送請求。
2>kafka的消費者組訂閱同一個topic蒿涎,會盡可能地使得每一個消費者分配到相同數(shù)量的分區(qū),分攤負載惦辛。
3>當消費者加入或者退出消費者組的時候,還會觸發(fā)再均衡胖齐,為每一個消費者重新分配分區(qū),分攤負載呀伙。
kafka的負載均衡大部分是自動完成的舅世,分區(qū)的創(chuàng)建也是kafka完成的日丹,隱藏了很多細節(jié)逛钻,避免了繁瑣的配置和人為疏忽造成的負載問題谚攒。
4>發(fā)送端由topic和key來決定消息發(fā)往哪個分區(qū)戚篙,如果key為null,那么會使用輪詢算法將消息均衡地發(fā)送到同一個topic的不同分區(qū)中位喂。如果key不為null,那么會根據(jù)key的hashcode取模計算出要發(fā)往的分區(qū)七冲。
rabbitmq:對負載均衡的支持不好规婆。
1>消息被投遞到哪個隊列是由交換器和key決定的,交換器掘鄙、路由鍵嗡髓、隊列都需要手動創(chuàng)建饿这。
rabbitmq客戶端發(fā)送消息要和broker建立連接,需要事先知道broker上有哪些交換器长捧,有哪些隊列。通常要聲明要發(fā)送的目標隊列哑子,如果沒有目標隊列奉芦,會在broker上創(chuàng)建一個隊列声功,如果有宠叼,就什么都不處理冒冬,接著往這個隊列發(fā)送消息。假設(shè)大部分繁重任務(wù)的隊列都創(chuàng)建在同一個broker上剂邮,那么這個broker的負載就會過大横侦。(可以在上線前預(yù)先創(chuàng)建隊列,無需聲明要發(fā)送的隊列引瀑,但是發(fā)送時不會嘗試創(chuàng)建隊列憨栽,可能出現(xiàn)找不到隊列的問題,rabbitmq的備份交換器會把找不到隊列的消息保存到一個專門的隊列中屡萤,以便以后查詢使用)
使用鏡像隊列機制建立rabbitmq集群可以解決這個問題掸宛,形成master-slave的架構(gòu)旁涤,master節(jié)點會均勻分布在不同的服務(wù)器上,讓每一臺服務(wù)器分攤負載瞳遍。slave節(jié)點只是負責(zé)轉(zhuǎn)發(fā)菌羽,在master失效時會選擇加入時間最長的slave成為master注祖。
當新節(jié)點加入鏡像隊列的時候,隊列中的消息不會同步到新的slave中肚菠,除非調(diào)用同步命令罩缴,但是調(diào)用命令后箫章,隊列會阻塞,不能在生產(chǎn)環(huán)境中調(diào)用同步命令终抽。
2>當rabbitmq隊列擁有多個消費者的時候,隊列收到的消息將以輪詢的分發(fā)方式發(fā)送給消費者匾旭。每條消息只會發(fā)送給訂閱列表里的一個消費者亩码,不會重復(fù)描沟。
這種方式非常適合擴展,而且是專門為并發(fā)程序設(shè)計的泞遗。
如果某些消費者的任務(wù)比較繁重史辙,那么可以設(shè)置basicQos限制信道上消費者能保持的最大未確認消息的數(shù)量佩伤,在達到上限時,rabbitmq不再向這個消費者發(fā)送任何消息耙蔑。
3>對于rabbitmq而言甸陌,客戶端與集群建立的TCP連接不是與集群中所有的節(jié)點建立連接盐股,而是挑選其中一個節(jié)點建立連接疯汁。
但是rabbitmq集群可以借助HAProxy、LVS技術(shù)秸谢,或者在客戶端使用算法實現(xiàn)負載均衡霹肝,引入負載均衡之后沫换,各個客戶端的連接可以分攤到集群的各個節(jié)點之中。
客戶端均衡算法:
1)輪詢法垮兑。按順序返回下一個服務(wù)器的連接地址漱挎。
2)加權(quán)輪詢法磕谅。給配置高、負載低的機器配置更高的權(quán)重衬浑,讓其處理更多的請求工秩;而配置低进统、負載高的機器,給其分配較低的權(quán)重眉菱,降低其系統(tǒng)負載倍谜。
3)隨機法叉抡。隨機選取一個服務(wù)器的連接地址褥民。
4)加權(quán)隨機法。按照概率隨機選取連接地址载弄。
5)源地址哈希法撵颊。通過哈希函數(shù)計算得到的一個數(shù)值倡勇,用該數(shù)值對服務(wù)器列表的大小進行取模運算。
6)最小連接數(shù)法夸浅。動態(tài)選擇當前連接數(shù)最少的一臺服務(wù)器的連接地址帆喇。
zeromq:去中心化,不支持負載均衡预皇。本身只是一個多線程網(wǎng)絡(luò)庫深啤。
rocketmq:支持負載均衡路星。
一個broker通常是一個服務(wù)器節(jié)點洋丐,broker分為master和slave,master和slave存儲的數(shù)據(jù)一樣,slave從master同步數(shù)據(jù)堤尾。
1>nameserver與每個集群成員保持心跳郭宝,保存著Topic-Broker路由信息掷漱,同一個topic的隊列會分布在不同的服務(wù)器上卜范。
2>發(fā)送消息通過輪詢隊列的方式發(fā)送,每個隊列接收平均的消息量锦爵。發(fā)送消息指定topic险掀、tags湾宙、keys,無法指定投遞到哪個隊列(沒有意義嗡害,集群消費和廣播消費跟消息存放在哪個隊列沒有關(guān)系)霸妹。
tags選填叹螟,類似于 Gmail 為每封郵件設(shè)置的標簽台盯,方便服務(wù)器過濾使用静盅。目前只支 持每個消息設(shè)置一個 tag,所以也可以類比為 Notify 的 MessageType 概念明垢。
keys選填痊银,代表這條消息的業(yè)務(wù)關(guān)鍵詞施绎,服務(wù)器會根據(jù) keys 創(chuàng)建哈希索引谷醉,設(shè)置后, 可以在 Console 系統(tǒng)根據(jù) Topic豺裆、Keys 來查詢消息臭猜,由于是哈希索引押蚤,請盡可能 保證 key 唯一揽碘,例如訂單號,商品 Id 等劫灶。
3>rocketmq的負載均衡策略規(guī)定:Consumer數(shù)量應(yīng)該小于等于Queue數(shù)量本昏,如果Consumer超過Queue數(shù)量涌穆,那么多余的Consumer 將不能消費消息。這一點和kafka是一致的趁舀,rocketmq會盡可能地為每一個Consumer分配相同數(shù)量的隊列矮烹,分攤負載奋隶。
activemq:支持負載均衡唯欣。可以基于zookeeper實現(xiàn)負載均衡蟀拷。
七问芬、集群方式
Kafka:天然的‘Leader-Slave’無狀態(tài)集群此衅,每臺服務(wù)器既是Master也是Slave亭螟。
分區(qū)首領(lǐng)均勻地分布在不同的kafka服務(wù)器上预烙,分區(qū)副本也均勻地分布在不同的kafka服務(wù)器上扁掸,所以每一臺kafka服務(wù)器既含有分區(qū)首領(lǐng)最域,同時又含有分區(qū)副本镀脂,每一臺kafka服務(wù)器是某一臺kafka服務(wù)器的Slave掐隐,同時也是某一臺kafka服務(wù)器的leader虑省。
kafka的集群依賴于zookeeper探颈,zookeeper支持熱擴展训措,所有的broker绩鸣、消費者呀闻、分區(qū)都可以動態(tài)加入移除,而無需關(guān)閉服務(wù)蓖康,與不依靠zookeeper集群的mq相比蒜焊,這是最大的優(yōu)勢泳梆。
rabbitmq:支持簡單集群榜掌,'復(fù)制'模式唐责,對高級集群模式支持不好鼠哥。
rabbitmq的每一個節(jié)點看政,不管是單一節(jié)點系統(tǒng)或者是集群中的一部分允蚣,要么是內(nèi)存節(jié)點嚷兔,要么是磁盤節(jié)點冒晰,集群中至少要有一個是磁盤節(jié)點竟块。
在rabbitmq集群中創(chuàng)建隊列浪秘,集群只會在單個節(jié)點創(chuàng)建隊列進程和完整的隊列信息(元數(shù)據(jù)耸携、狀態(tài)夺衍、內(nèi)容),而不是在所有節(jié)點上創(chuàng)建的畴。
引入鏡像隊列丧裁,可以避免單點故障煎娇,確保服務(wù)的可用性贪染,但是需要人為地為某些重要的隊列配置鏡像杭隙。
zeromq:去中心化痰憎,不支持集群。
rocketmq:常用 多對'Master-Slave' 模式以故,開源版本需手動切換Slave變成Master
Name Server是一個幾乎無狀態(tài)節(jié)點怒详,可集群部署踪区,節(jié)點之間無任何信息同步缎岗。
Broker部署相對復(fù)雜密强,Broker分為Master與Slave蜗元,一個Master可以對應(yīng)多個Slave奕扣,但是一個Slave只能對應(yīng)一個Master惯豆,Master與Slave的對應(yīng)關(guān)系通過指定相同的BrokerName楷兽,不同的BrokerId來定義芯杀,BrokerId為0表示Master,非0表示Slave揭厚。Master也可以部署多個却特。每個Broker與Name Server集群中的所有節(jié)點建立長連接,定時注冊Topic信息到所有Name Server筛圆。
Producer與Name Server集群中的其中一個節(jié)點(隨機選擇)建立長連接裂明,定期從Name Server取Topic路由信息,并向提供Topic服務(wù)的Master建立長連接太援,且定時向Master發(fā)送心跳闽晦。Producer完全無狀態(tài)扳碍,可集群部署尼荆。
Consumer與Name Server集群中的其中一個節(jié)點(隨機選擇)建立長連接左腔,定期從Name Server取Topic路由信息,并向提供Topic服務(wù)的Master捅儒、Slave建立長連接液样,且定時向Master、Slave發(fā)送心跳巧还。Consumer既可以從Master訂閱消息鞭莽,也可以從Slave訂閱消息,訂閱規(guī)則由Broker配置決定麸祷。
客戶端先找到NameServer, 然后通過NameServer再找到 Broker澎怒。
一個topic有多個隊列,這些隊列會均勻地分布在不同的broker服務(wù)器上阶牍。rocketmq隊列的概念和kafka的分區(qū)概念是基本一致的喷面,kafka同一個topic的分區(qū)盡可能地分布在不同的broker上,分區(qū)副本也會分布在不同的broker上走孽。
rocketmq集群的slave會從master拉取數(shù)據(jù)備份惧辈,master分布在不同的broker上。
activemq:支持簡單集群模式磕瓷,比如'主-備'盒齿,對高級集群模式支持不好。
八困食、管理界面
Kafka:一般 rabbitmq:好 zeromq:無 rocketmq:無 activemq:一般
九边翁、可用性
Kafka:非常高(分布式) rabbitmq:高(主從) zeromq:高。rocketmq:非常高(分布式) activemq:高(主從)
十硕盹、消息重復(fù)
Kafka:支持at least once符匾、at most once
rabbitmq:支持at least once、at most once
zeromq:只有重傳機制莱睁,但是沒有持久化待讳,消息丟了重傳也沒有用。既不是at least once仰剿、也不是at most once创淡、更不是exactly only once
rocketmq:支持at least once
activemq:支持at least once
十一、吞吐量TPS
Kafka:極大 Kafka按批次發(fā)送消息和消費消息南吮。發(fā)送端將多個小消息合并琳彩,批量發(fā)向Broker,消費端每次取出一個批次的消息批量處理。rabbitmq:比較大 zeromq:極大 rocketmq:大 rocketMQ接收端可以批量消費消息露乏,可以配置每次消費的消息數(shù)碧浊,但是發(fā)送端不是批量發(fā)送。activemq:比較大
十二瘟仿、訂閱形式和消息分發(fā)
Kafka:基于topic以及按照topic進行正則匹配的發(fā)布訂閱模式箱锐。
【發(fā)送】
發(fā)送端由topic和key來決定消息發(fā)往哪個分區(qū),如果key為null劳较,那么會使用輪詢算法將消息均衡地發(fā)送到同一個topic的不同分區(qū)中驹止。如果key不為null,那么會根據(jù)key的hashcode取模計算出要發(fā)往的分區(qū)观蜗。
【接收】
1>consumer向群組協(xié)調(diào)器broker發(fā)送心跳來維持他們和群組的從屬關(guān)系以及他們對分區(qū)的所有權(quán)關(guān)系臊恋,所有權(quán)關(guān)系一旦被分配就不會改變除非發(fā)生再均衡(比如有一個consumer加入或者離開consumer group),consumer只會從對應(yīng)的分區(qū)讀取消息墓捻。
2>kafka限制consumer個數(shù)要少于分區(qū)個數(shù),每個消息只會被同一個 Consumer Group的一個consumer消費(非廣播)抖仅。
3>kafka的 Consumer Group訂閱同一個topic,會盡可能地使得每一個consumer分配到相同數(shù)量的分區(qū)砖第,不同 Consumer Group訂閱同一個主題相互獨立撤卢,同一個消息會被不同的 Consumer Group處理。
rabbitmq:提供了4種:direct, topic ,Headers和fanout梧兼。
【發(fā)送】
先要聲明一個隊列凸丸,這個隊列會被創(chuàng)建或者已經(jīng)被創(chuàng)建,隊列是基本存儲單元袱院。
由exchange和key決定消息存儲在哪個隊列。
direct>發(fā)送到和bindingKey完全匹配的隊列瞭稼。
topic>路由key是含有"."的字符串忽洛,會發(fā)送到含有“*”、“#”進行模糊匹配的bingKey對應(yīng)的隊列环肘。
fanout>與key無關(guān)欲虚,會發(fā)送到所有和exchange綁定的隊列
headers>與key無關(guān),消息內(nèi)容的headers屬性(一個鍵值對)和綁定鍵值對完全匹配時悔雹,會發(fā)送到此隊列复哆。此方式性能低一般不用
【接收】
rabbitmq的隊列是基本存儲單元,不再被分區(qū)或者分片腌零,對于我們已經(jīng)創(chuàng)建了的隊列梯找,消費端要指定從哪一個隊列接收消息。
當rabbitmq隊列擁有多個消費者的時候益涧,隊列收到的消息將以輪詢的分發(fā)方式發(fā)送給消費者锈锤。每條消息只會發(fā)送給訂閱列表里的一個消費者,不會重復(fù)。
這種方式非常適合擴展久免,而且是專門為并發(fā)程序設(shè)計的浅辙。
如果某些消費者的任務(wù)比較繁重,那么可以設(shè)置basicQos限制信道上消費者能保持的最大未確認消息的數(shù)量阎姥,在達到上限時记舆,rabbitmq不再向這個消費者發(fā)送任何消息。
zeromq:點對點(p2p)
rocketmq:基于topic/messageTag以及按照消息類型呼巴、屬性進行正則匹配的發(fā)布訂閱模式
【發(fā)送】
發(fā)送消息通過輪詢隊列的方式發(fā)送泽腮,每個隊列接收平均的消息量。發(fā)送消息指定topic伊磺、tags盛正、keys,無法指定投遞到哪個隊列(沒有意義屑埋,集群消費和廣播消費跟消息存放在哪個隊列沒有關(guān)系)豪筝。
tags選填,類似于 Gmail 為每封郵件設(shè)置的標簽摘能,方便服務(wù)器過濾使用续崖。目前只支 持每個消息設(shè)置一個 tag,所以也可以類比為 Notify 的 MessageType 概念团搞。
keys選填严望,代表這條消息的業(yè)務(wù)關(guān)鍵詞,服務(wù)器會根據(jù) keys 創(chuàng)建哈希索引逻恐,設(shè)置后像吻, 可以在 Console 系統(tǒng)根據(jù) Topic、Keys 來查詢消息复隆,由于是哈希索引拨匆,請盡可能 保證 key 唯一,例如訂單號挽拂,商品 Id 等惭每。
【接收】
1>廣播消費。一條消息被多個Consumer消費亏栈,即使Consumer屬于同一個ConsumerGroup台腥,消息也會被ConsumerGroup中的每個Consumer都消費一次。
2>集群消費绒北。一個 Consumer Group中的Consumer實例平均分攤消費消息黎侈。例如某個Topic有 9 條消息,其中一個Consumer Group有3個實例闷游,那么每個實例只消費其中的 3 條消息蜓竹。即每一個隊列都把消息輪流分發(fā)給每個consumer箕母。
activemq:點對點(p2p)、廣播(發(fā)布-訂閱)
點對點模式俱济,每個消息只有1個消費者嘶是;
發(fā)布/訂閱模式,每個消息可以有多個消費者蛛碌。
【發(fā)送】
點對點模式:先要指定一個隊列聂喇,這個隊列會被創(chuàng)建或者已經(jīng)被創(chuàng)建。
發(fā)布/訂閱模式:先要指定一個topic蔚携,這個topic會被創(chuàng)建或者已經(jīng)被創(chuàng)建希太。
【接收】
點對點模式:對于已經(jīng)創(chuàng)建了的隊列,消費端要指定從哪一個隊列接收消息酝蜒。
發(fā)布/訂閱模式:對于已經(jīng)創(chuàng)建了的topic誊辉,消費端要指定訂閱哪一個topic的消息。
十三亡脑、順序消息
Kafka:支持堕澄。
設(shè)置生產(chǎn)者的max.in.flight.requests.per.connection為1,可以保證消息是按照發(fā)送順序?qū)懭敕?wù)器的霉咨,即使發(fā)生了重試蛙紫。
kafka保證同一個分區(qū)里的消息是有序的,但是這種有序分兩種情況
1>key為null途戒,消息逐個被寫入不同主機的分區(qū)中坑傅,但是對于每個分區(qū)依然是有序的
2>key不為null , 消息被寫入到同一個分區(qū),這個分區(qū)的消息都是有序喷斋。
rabbitmq:不支持
zeromq:不支持
rocketmq:支持
activemq:不支持
十四唁毒、消息確認
Kafka:支持。
1>發(fā)送方確認機制
ack=0星爪,不管消息是否成功寫入分區(qū)
ack=1枉证,消息成功寫入首領(lǐng)分區(qū)后,返回成功
ack=all移必,消息成功寫入所有分區(qū)后,返回成功毡鉴。
2>接收方確認機制
自動或者手動提交分區(qū)偏移量崔泵,早期版本的kafka偏移量是提交給Zookeeper的,這樣使得zookeeper的壓力比較大猪瞬,更新版本的kafka的偏移量是提交給kafka服務(wù)器的憎瘸,不再依賴于zookeeper群組,集群的性能更加穩(wěn)定陈瘦。
rabbitmq:支持幌甘。
1>發(fā)送方確認機制,消息被投遞到所有匹配的隊列后,返回成功锅风。如果消息和隊列是可持久化的酥诽,那么在寫入磁盤后,返回成功皱埠。支持批量確認和異步確認肮帐。
2>接收方確認機制,設(shè)置autoAck為false边器,需要顯式確認训枢,設(shè)置autoAck為true,自動確認忘巧。
當autoAck為false的時候恒界,rabbitmq隊列會分成兩部分,一部分是等待投遞給consumer的消息砚嘴,一部分是已經(jīng)投遞但是沒收到確認的消息十酣。如果一直沒有收到確認信號,并且consumer已經(jīng)斷開連接枣宫,rabbitmq會安排這個消息重新進入隊列婆誓,投遞給原來的消費者或者下一個消費者。
未確認的消息不會有過期時間也颤,如果一直沒有確認洋幻,并且沒有斷開連接,rabbitmq會一直等待翅娶,rabbitmq允許一條消息處理的時間可以很久很久文留。
zeromq:支持。
rocketmq:支持竭沫。
activemq:支持燥翅。
十五、消息回溯
Kafka:支持指定分區(qū)offset位置的回溯蜕提。rabbitmq:不支持 zeromq:不支持 rocketmq:支持指定時間點的回溯森书。activemq:不支持
十六、消息重試
Kafka:不支持谎势,但是可以實現(xiàn)凛膏。
kafka支持指定分區(qū)offset位置的回溯,可以實現(xiàn)消息重試脏榆。
rabbitmq:不支持猖毫,但是可以利用消息確認機制實現(xiàn)。
rabbitmq接收方確認機制须喂,設(shè)置autoAck為false吁断。
當autoAck為false的時候趁蕊,rabbitmq隊列會分成兩部分,一部分是等待投遞給consumer的消息仔役,一部分是已經(jīng)投遞但是沒收到確認的消息掷伙。如果一直沒有收到確認信號,并且consumer已經(jīng)斷開連接骂因,rabbitmq會安排這個消息重新進入隊列炎咖,投遞給原來的消費者或者下一個消費者。
zeromq:不支持寒波,
rocketmq:支持乘盼。
消息消費失敗的大部分場景下,立即重試99%都會失敗俄烁,所以rocketmq的策略是在消費失敗時定時重試绸栅,每次時間間隔相同。
1>發(fā)送端的 send 方法本身支持內(nèi)部重試页屠,重試邏輯如下:
a)至多重試3次粹胯;
b)如果發(fā)送失敗,則輪轉(zhuǎn)到下一個broker辰企;
c)這個方法的總耗時不超過sendMsgTimeout 設(shè)置的值风纠,默認 10s,超過時間不在重試牢贸。
2>接收端竹观。
Consumer 消費消息失敗后,要提供一種重試機制潜索,令消息再消費一次臭增。Consumer 消費消息失敗通常可以分為以下兩種情況:
由于消息本身的原因竹习,例如反序列化失敗誊抛,消息數(shù)據(jù)本身無法處理(例如話費充值,當前消息的手機號被
注銷整陌,無法充值)等拗窃。定時重試機制,比如過 10s 秒后再重試泌辫。
由于依賴的下游應(yīng)用服務(wù)不可用随夸,例如 db 連接不可用,外系統(tǒng)網(wǎng)絡(luò)不可達等甥郑。
即使跳過當前失敗的消息,消費其他消息同樣也會報錯荤西。這種情況可以 sleep 30s澜搅,再消費下一條消息伍俘,減輕 Broker 重試消息的壓力。
activemq:不支持
十七勉躺、并發(fā)度
Kafka:高
一個線程一個消費者癌瘾,kafka限制消費者的個數(shù)要小于等于分區(qū)數(shù),如果要提高并行度饵溅,可以在消費者中再開啟多線程妨退,或者增加consumer實例數(shù)量。
rabbitmq:極高
本身是用Erlang語言寫的蜕企,并發(fā)性能高咬荷。
可在消費者中開啟多線程,最常用的做法是一個channel對應(yīng)一個消費者轻掩,每一個線程把持一個channel幸乒,多個線程復(fù)用connection的tcp連接,減少性能開銷唇牧。
當rabbitmq隊列擁有多個消費者的時候罕扎,隊列收到的消息將以輪詢的分發(fā)方式發(fā)送給消費者。每條消息只會發(fā)送給訂閱列表里的一個消費者丐重,不會重復(fù)腔召。
這種方式非常適合擴展,而且是專門為并發(fā)程序設(shè)計的扮惦。
如果某些消費者的任務(wù)比較繁重臀蛛,那么可以設(shè)置basicQos限制信道上消費者能保持的最大未確認消息的數(shù)量,在達到上限時径缅,rabbitmq不再向這個消費者發(fā)送任何消息掺栅。
zeromq:高
rocketmq:高
1>rocketmq限制消費者的個數(shù)少于等于隊列數(shù),但是可以在消費者中再開啟多線程纳猪,這一點和kafka是一致的氧卧,提高并行度的方法相同。
修改消費并行度方法
a) 同一個 ConsumerGroup 下氏堤,通過增加 Consumer 實例數(shù)量來提高并行度沙绝,超過訂閱隊列數(shù)的 Consumer實例無效。
b) 提高單個 Consumer 的消費并行線程鼠锈,通過修改參數(shù)consumeThreadMin闪檬、consumeThreadMax
2>同一個網(wǎng)絡(luò)連接connection,客戶端多個線程可以同時發(fā)送請求购笆,連接會被復(fù)用粗悯,減少性能開銷。
activemq:高
單個ActiveMQ的接收和消費消息的速度在1萬筆/秒(持久化 一般為1-2萬同欠, 非持久化 2 萬以上)样傍,在生產(chǎn)環(huán)境中部署10個Activemq就能達到10萬筆/秒以上的性能横缔,部署越多的activemq broker 在MQ上latency也就越低,系統(tǒng)吞吐量也就越高衫哥。