以前本人在實際的生產環境中,使用過activemq和rabbitmq消息隊列,在使用過程當中出現一些難以解決的問題,本文經過產品選型、網絡架構和核心特性分析了rocketmq的優點和特性。
java
產品選型程序員
咱們在進行中間件選型時,通常都是經過下面幾點來進行產品選型的:數據庫
1.性能後端
2.功能支持程度服務器
3.開發語言(團隊中是否有成員熟悉此中間件的開發語言,市場上此種語言的開發人員是否好招)網絡
4.有多少公司已經在生產環境上實際使用過,使用的效果如何架構
5.社區的支持力度如何異步
6.中間件的學習程度是否簡單、文檔是否詳盡性能
7.穩定性學習
8.集羣功能是否完備
...
若是從以上8點來選型一個消息隊列,做爲一名熟悉java的程序員,當遇到從新選擇消息隊列的場景時,我會堅決果斷的選型rocketmq,rocketmq除了在第5點上表現略差(文檔少,學習成本高)以及監控管理功能不友好外,從其它方面來講,它真的是一款很是優秀的消息隊列中間件。
網絡架構
(圖片來源於官方文檔)
rocketmq的主要部分是由4種集羣構成的:namesrv集羣、broker集羣、producer集羣和consumer集羣。
namesrv集羣:也就是註冊中心,rocketmq在註冊中心這塊沒有使用第三方的中間件,而是本身寫的代碼來實現的,代碼行數才1000行,producer、broker和consumer在啓動時都須要向namesrv進行註冊,namesrv服務之間不通信。
broker集羣:broker提供關於消息的管理、存儲、分發等功能,是消息隊列的核心組件。rocket關於broker的集羣提供了主要兩種方案,一種是主從同步方案,消息同時寫到master和slave服務器視爲消息發送成功;另外一種是異步方案,slave的異步服務負責讀取master的數據,本人在選擇時更傾向於異步方案。
producer集羣:消息的生產者,每一個producer都須要屬於一個group,producer的group概念除了在事務消息時起到一些做用,可是其它時候,更多的還只是一個虛擬的概念。
consumer集羣:消息的消費者,有兩個主要的consumer:DefaultMQPullConsumer和DefaultMQPushConsumer,深刻代碼後能夠發現,rocket的consumer都是採用的pull模式來處理消息的。在集羣消息的配置下,集羣內各個服務平均分配消息,當其中一臺consumer宕機,分配給它的消息會繼續分配給其它的consumer。
核心特性
1.讀隊列數量和寫隊列數量能夠不一致:當咱們使用updateTopic命令建立topic時,會發現新建的topic下會有默認的8個寫對列和8個讀對列(依賴於配置),而且讀隊列的數量和寫隊列的數量還能夠不一致,這是爲何呢?難道在底層讀寫隊列是在物理上分離的嗎?抱着這個問題,我分析了相關的源代碼,發現底層代碼對於讀寫隊列指的都是同一個隊列,其中寫隊列的數量是針對的producer,讀隊列的數量針對的是consumer:
a.假設寫隊列有8個、讀隊列有4個,那麼producer產生的消息會按輪訓的方式寫入到8個隊列中,可是consumer卻只能消費前4個隊列,只有把讀隊列從新設置爲8後,consumer能夠繼續消費後4個隊列的歷史消息;
b.假設寫隊列有4個、讀隊列有8個,那麼producer產生的消息會按輪訓的方式寫入到4個隊列中,可是consumer卻能消費8個隊列,只是後4個隊列沒有消息能夠消費罷了。
2.存儲爲文件存儲方式,支持同步落盤和異步刷盤兩種方式,我傾向於選擇異步刷盤的方式,畢竟broker掛掉的機率比較小,大部分的業務場景下在極端狀況下丟失及其少許消息是能夠忍受的;
3.支持消息回溯,支持按期刪除歷史消息;
4.集羣方案比activemq要優秀不少,支持多主多從方案,例如在2主2從異步架構下,a,b爲master,as,bs爲slaver,當a機宕機後,producer會將消息所有發往b機,consumer會消費as,b和bs上的消息,理論上只會丟失毫秒級別的消息,不會影響業務的正常使用。能夠說rocketmq的集羣方案完爆activemq的集羣方案,不少時候,咱們對於異步隊列的性能要求不高,可是集羣的可用性要求必定是很高的。下面是activemq的三種集羣方案:
a.磁盤陣列類,成本較高,也是一種通用的方案;
b.利用jdbc來實現統一存儲消息,不但性能成問題,並且也只是把問題丟給了數據庫罷了,沒有解決集羣的單機問題;
c.利用zookeeper的註冊中心的選主功能,在各個服務之間同步數據,在實際的使用過程當中發現主機自動漂移,同步數據不徹底形成的數據錯亂且服務啓動不了,反而不如單機來的穩定;
5.隊列數量單機支持10000個以上;
6.consumer支持集羣功能,能夠平均消費消息,當有一臺consumer宕機後,其它consumer繼續均分;
7.consumer是靠pull的方式來消費消息的,性能不低於push的方式,這也是broker的並行能力強的一個緣由,將主動權下放給了consumer,下降了broker的運算量和線程切換成本;
8.支持順序消息,能夠在發送消息時,利用selector機制的hash方式取模來實現消息落到哪一個broker的哪一個queue上,當某個broker宕機後,因爲取模值也發生變化,會自動切換隊列;
9.producer發送消息時支持同步返回、異步返回和oneway三種方式;
10.broker保證每條消息至少投遞到consumer一次,所以consumer的業務須要支持冪等;
11.消息堆積能力驚人,消息隊列的一個做用即是防止洪峯直接沖垮後端業務;
12.支持按照消息id和消息key來查詢消息,本人很喜歡按照key來查詢消息這個功能,例如在下單業務中,可使用訂單id做爲key,便於分析異常訂單在系統中的處理過程;
13.支持消息過濾;
...