簡介
上圖是一個典型的消息中間件收發(fā)消息的模型奠蹬,RocketMQ也是這樣的設計朝聋,簡單說來,RocketMQ具有以下特點:
- 是一個隊列模型的消息中間件囤躁,具有高性能冀痕、高可靠、高實時狸演、分布式特點金度。
- Producer、Consumer严沥、隊列都可以分布式猜极。
- Producer向一些隊列輪流發(fā)送消息,隊列集合稱為Topic消玄,Consumer如果做廣播消費跟伏,則一個consumer實例消費這個Topic對應的所有隊列,如果做集群消費翩瓜,則多個Consumer實例平均消費這個topic對應的隊列集合受扳。
- 能夠保證嚴格的消息順序
- 提供豐富的消息拉取模式
- 高效的訂閱者水平擴展能力
- 實時的消息訂閱機制
- 億級消息堆積能力
- 較少的依賴
rocketmq的物理部署結(jié)構(gòu):
- Name Server是一個幾乎無狀態(tài)節(jié)點,可集群部署兔跌,節(jié)點之間無任何信息同步勘高。
- Broker部署相對復雜,Broker分為Master與Slave坟桅,一個Master可以對應多個Slave华望,但是一個Slave只能對應一個Master,Master與Slave的對應關(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服務的Master建立長連接紧显,且定時向Master發(fā)送心跳讲衫。Producer完全無狀態(tài),可集群部署鸟妙。
支持的特性
- 發(fā)布/訂閱焦人。
- 優(yōu)先級挥吵,支持隊列優(yōu)先級,數(shù)字表達花椭。
- 消息順序的嚴格保證忽匈。
- 消息過濾,Broker端過濾:支持類型矿辽,tag丹允,語法表達式過濾;Consumer端過濾:自定義實現(xiàn)即可袋倔。
- 持久化雕蔽,充分利用linux系統(tǒng)內(nèi)存cache提升性能。
- 消息可靠性宾娜,支持異步批狐,同步雙寫。
- 低延遲前塔,在消息不堆積情況下嚣艇,消息到達Broker后,能立刻到達Consumer华弓。RocketMQ使用長輪詢Pull方式 長輪詢詳解食零,可保證消息非常實時,消息實時性不低于Push寂屏。
- 每個消息必須消費并ack一次贰谣。
- 隊列持久化,定期刪除某段時間之前的數(shù)據(jù)迁霎。
- 回溯消費吱抚,支持往前,往后欧引,按照時間频伤,可達毫秒級別。
- 消息堆積芝此,
- 分布式事務,根據(jù)offset更改msg狀態(tài)因痛。
- 定時消息婚苹,支持級別,5s,5s,1m鸵膏。
- 消息重試膊升,
架構(gòu)圖
- producer集群:擁有相同的producerGroup,一般來講,Producer不必要有集群的概念谭企,這里的集群僅僅在RocketMQ的分布式事務中有用到
- Name Server集群:提供topic的路由信息廓译,路由信息數(shù)據(jù)存儲在內(nèi)存中评肆,broker會定時的發(fā)送路由信息到nameserver中的每一個機器,來進行更新非区,所以name server集群可以簡單理解為無狀態(tài)(實際情況下可能存在每個nameserver機器上的數(shù)據(jù)有短暫的不一致現(xiàn)象瓜挽,但是通過定時更新,大部分情況下都是一致的)
- broker集群:一個集群有一個統(tǒng)一的名字征绸,即brokerClusterName久橙,默認是DefaultCluster。一個集群下有多個master管怠,每個master下有多個slave淆衷。master和slave算是一組,擁有相同的brokerName,不同的brokerId渤弛,master的brokerId是0祝拯,而slave則是大于0的值。master和slave之間可以進行同步復制或者是異步復制她肯。
- consumer集群:擁有相同的consumerGroup佳头。
通信關(guān)系:
對比其他mq
消息存儲
為提高消息讀寫并發(fā)能力,將一個topic消息進行拆分辕宏,kafka稱為分區(qū)畜晰,rocketmq稱為隊列。
- 對于kafka:為了防止一個分區(qū)的消息文件過大瑞筐,會拆分成一個個固定大小的文件凄鼻,所以一個分區(qū)就對應了一個目錄。分區(qū)與分區(qū)之間是相互隔離的聚假。
- 對于RocketMQ:則是所有topic的數(shù)據(jù)混在一起進行存儲块蚌,默認超過1G的話,則重新創(chuàng)建一個新的文件膘格。消息的寫入過程即寫入該混雜的文件中峭范,然后又有一個線程服務,在不斷的讀取分析該混雜文件瘪贱,將消息進行分揀纱控,然后存儲在對應隊列目錄中(存儲的是簡要信息,如消息在混雜文件中的offset菜秦,消息大小等)
-
所以RocketMQ需要2次尋找甜害,第一次先找隊列中的消息概要信息,拿到概要信息中的offset球昨,根據(jù)這個offset再到混雜文件中找到想要的消息尔店。而kafka則只需要直接讀取分區(qū)中的文件即可得到想要的消息。
producer端發(fā)現(xiàn)
Producer端如何來發(fā)現(xiàn)新的broker地址。
對于kafka來說:Producer端需要配置broker的列表地址嚣州,Producer也從一個broker中來更新broker列表地址(從中發(fā)現(xiàn)新加入的broker)鲫售。
對于RocketMQ來說:Producer端需要Name Server的列表地址,同時還可以定時從一個HTTP地址中來獲取最新的Name Server的列表地址该肴,然后從其中的一臺Name Server來獲取全部的路由信息情竹,從中發(fā)現(xiàn)新的broker。
消費offset的存儲
對于kafka:Consumer將消費的offset定時存儲到ZooKeeper上沙庐,利用ZooKeeper保障了offset的高可用問題鲤妥。
對于RocketMQ:Consumer將消費的offset定時存儲到broker所在的機器上,這個broker優(yōu)先是master拱雏,如果master掛了的話棉安,則會選擇slave來存儲,broker也是將這些offset定時刷新到本地磁盤上铸抑,同時slave會定時的訪問master來獲取這些offset贡耽。
consumer負載均衡
對于負載均衡,在出現(xiàn)分區(qū)或者隊列增加或者減少的時候鹊汛、Consumer增加或者減少的時候都會進行reblance操作蒲赂。
對于RocketMQ:客戶端自己會定時對所有的topic的進行reblance操作,對于每個topic刁憋,會從broker獲取所有Consumer列表滥嘴,從broker獲取隊列列表,按照負載均衡策略至耻,計算各自負責哪些隊列若皱。這種就要求進行負載均衡的時候,各個Consumer獲取的數(shù)據(jù)是一致的尘颓,不然不同的Consumer的reblance結(jié)果就不同走触。
對于kafka:kafka之前也是客戶端自己進行reblance,依靠ZooKeeper的監(jiān)聽疤苹,來監(jiān)聽上述2種情況的出現(xiàn)互广,一旦出現(xiàn)則進行reblance。現(xiàn)在的版本則將這個reblance操作轉(zhuǎn)移到了broker端來做卧土,不但解決了RocketMQ上述的問題惫皱,同時減輕了客戶端的操作,是的客戶端更加輕量級尤莺,減少了和其他語言集成的工作量逸吵。詳細見這篇文章Kafka設計解析(四):Kafka Consumer解析
Name Server和zk
Name Server和ZooKeeper的作用大致是相同的,從宏觀上來看缝裁,Name Server做的東西很少,就是保存一些運行數(shù)據(jù),Name Server之間不互連捷绑,這就需要broker端連接所有的Name Server韩脑,運行數(shù)據(jù)的改動要發(fā)送到每一個Name Server來保證運行數(shù)據(jù)的一致性(這個一致性確實有點弱),這樣就變成了Name Server很輕量級粹污,但是broker端就要做更多的東西了段多。
而ZooKeeper呢,broker只需要連接其中的一臺機器壮吩,運行數(shù)據(jù)分發(fā)进苍、一致性都交給了ZooKeeper來完成。
源碼解讀
參考文章
RocketMQ源碼分析(一)整體架構(gòu)
Kafka設計解析(四):Kafka Consumer解析
分布式開放消息系統(tǒng)(RocketMQ)的原理與實踐
十分鐘入門RocketMQ