本文首先引出消息中間件一般須要解決哪些問題,在解決這些問題當中會遇到什麼困難,Apache RocketMQ做爲阿里開源的一款高性能、高吞吐量的分佈式消息中間件否能夠解決,規範中如何定義這些問題。而後本文將介紹RocketMQ的架構設計,以期讓讀者快速瞭解RocketMQ。前端
發佈訂閱是消息中間件的最基本功能,也是相對於傳統RPC通訊而言。在此再也不詳述。sql
規範中描述的優先級是指在一個消息隊列中,每條消息都有不一樣的優先級,通常用整數來描述,優先級高的消息先投遞,若是消息徹底在一個內存隊列中,那麼在投遞前能夠按照優先級排序,令優先級高的先投遞。
因爲RocketMQ全部消息都是持久化的,因此若是按照優先級來排序,開銷會很是大,所以RocketMQ沒有特地支持消息優先級,可是能夠經過變通的方式實現相似功能,即單獨配置一個優先級高的隊列,和一個普通優先級的隊列, 將不一樣優先級發送到不一樣隊列便可。數據庫
對於優先級問題,能夠概括爲2類:後端
消息有序指的是一類消息消費時,能按照發送的順序來消費。例如:一個訂單產生了3條消息,分別是訂單建立,訂單付款,訂單完成。消費時,要按照這個順序消費纔能有意義。可是同時訂單之間是能夠並行消費的。
RocketMQ能夠嚴格的保證消息有序。服務器
在Broker中,按照Consumer的要求作過濾,優勢是減小了對於Consumer無用消息的網絡傳輸。
缺點是增長了Broker的負擔,實現相對複雜。網絡
這種過濾方式可由應用徹底自定義實現,可是缺點是不少無用的消息要傳輸到Consumer端。架構
消息中間件一般採用的幾種持久化方式:併發
JMS與CORBA Notification規範沒有明確說明如何持久化,可是持久化部分的性能直接決定了整個消息中間件的性能。運維
RocketMQ充分利用Linux文件系統內存cache來提升性能。異步
影響消息可靠性的幾種狀況:
(1)、(2)、(3)、(4)四種狀況都屬於硬件資源可當即恢復狀況,RocketMQ在這四種狀況下能保證消息不丟,或者丟失少許數據(依賴刷盤方式是同步仍是異步)。
(5)、(6)屬於單點故障,且沒法恢復,一旦發生,在此單點上的消息所有丟失。RocketMQ在這兩種狀況下,經過異步複製,可保證99%的消息不丟,可是仍然會有極少許的消息可能丟失。經過同步雙寫技術能夠徹底避免單點,同步雙寫勢必會影響性能,適合對消息可靠性要求極高的場合,例如與Money相關的應用。
RocketMQ從3.0版本開始支持同步雙寫。
在消息不堆積狀況下,消息到達Broker後,能馬上到達Consumer。
RocketMQ使用長輪詢Pull方式,可保證消息很是實時,消息實時性不低於Push。
是指每一個消息必須投遞一次。
RocketMQ Consumer先pull消息到本地,消費完成後,才向服務器返回ack,若是沒有消費必定不會ack消息,因此RocketMQ能夠很好的支持此特性。
只有以上兩個條件都知足狀況下,才能認爲消息是「Exactly Only Once」,而要實現以上兩點,在分佈式系統環境下,不可避免要產生巨大的開銷。因此RocketMQ爲了追求高性能,並不保證此特性,要求在業務上進行去重,也就是說消費消息要作到冪等性。RocketMQ雖然不能嚴格保證不重複,可是正常狀況下不多會出現重複發送、消費狀況,只有網絡異常,Consumer啓停等異常狀況下會出現消息重複。
Broker的Buffer一般指的是Broker中一個隊列的內存Buffer大小,這類Buffer一般大小有限,若是Buffer滿了之後怎麼辦?
下面是CORBA Notification規範中處理方式:
RocketMQ沒有內存Buffer概念,RocketMQ的隊列都是持久化磁盤,數據按期清除。
對於此問題的解決思路,RocketMQ同其餘MQ有很是顯著的區別,RocketMQ的內存Buffer抽象成一個無限長度的隊列,無論有多少數據進來都能裝得下,這個無限是有前提的,Broker會按期刪除過時的數據,例如Broker只保存3天的消息,那麼這個Buffer雖然長度無限,可是3天前的數據會被從隊尾刪除。
此問題的本質緣由是網絡調用存在不肯定性,即既不成功也不失敗的第三種狀態,因此才產生了消息重複性問題。
回溯消費是指Consumer已經消費成功的消息,因爲業務上需求須要從新消費,要支持此功能,Broker在向Consumer投遞成功消息後,消息仍然須要保留。而且從新消費通常是按照時間維度,例如因爲Consumer系統故障,恢復後須要從新消費1小時前的數據,那麼Broker要提供一種機制,能夠按照時間維度來回退消費進度。
RocketMQ支持按照時間回溯消費,時間維度精確到毫秒,能夠向前回溯,也能夠向後回溯。
消息中間件的主要功能是異步解耦,還有個重要功能是擋住前端的數據洪峯,保證後端系統的穩定性,這就要求消息中間件具備必定的消息堆積能力,消息堆積分如下兩種狀況:
評估消息堆積能力主要有如下四點:
已知的幾個分佈式事務規範,如XA,JTA等。其中XA規範被各大數據庫廠商普遍支持,如Oracle,Mysql等。其中XA的TM實現佼佼者如Oracle Tuxedo,在金融、電信等領域被普遍應用。
分佈式事務涉及到兩階段提交問題,在數據存儲方面的方面必然須要KV存儲的支持,由於第二階段的提交回滾須要修改消息狀態,必定涉及到根據Key去查找Message的動做。RocketMQ在第二階段繞過了根據Key去查找Message的問題,採用第一階段發送Prepared消息時,拿到了消息的Offset,第二階段經過Offset去訪問消息,並修改狀態,Offset就是數據的地址。
RocketMQ這種實現事務方式,沒有經過KV存儲作,而是經過Offset方式,存在一個顯著缺陷,即經過Offset更改數據,會令系統的髒頁過多,須要特別關注。
定時消息是指消息發到Broker後,不能馬上被Consumer消費,要到特定的時間點或者等待特定的時間後才能被消費。
若是要支持任意的時間精度,在Broker層面,必需要作消息排序,若是再涉及到持久化,那麼消息排序要不可避免的產生巨大性能開銷。
RocketMQ支持定時消息,可是不支持任意時間精度,支持特定的level,例如定時5s,10s,1m等。
Consumer消費消息失敗後,要提供一種重試機制,令消息再消費一次。Consumer消費消息失敗一般能夠認爲有如下幾種狀況:
RocketMQ是否解決了上述消息中間件面臨的問題,接下來讓咱們一探究竟。
上圖是一個典型的消息中間件收發消息的模型,RocketMQ也是這樣的設計,簡單說來,RocketMQ具備如下特色:
如上圖所示, RocketMQ的部署結構有如下特色:
如上圖所示,RocketMQ的邏輯部署結構有Producer和Consumer兩個特色。
Producer Group
用來表示一個發送消息應用,一個Producer Group下包含多個Producer實例,能夠是多臺機器,也能夠是一臺機器的多個進程,或者一個進程的多個Producer對象。一個Producer Group能夠發送多個Topic消息,Producer Group做用以下:
Consumer Group
用來表示一個消費消息應用,一個Consumer Group下包含多個Consumer實例,能夠是多臺機器,也能夠是多個進程,或者是一個進程的多個Consumer對象。一個Consumer Group下的多個Consumer以均攤方式消費消息,若是設置爲廣播方式,那麼這個Consumer Group下的每一個實例都消費全量數據。
如上圖所示,RocketMQ採起了一種數據與索引分離的存儲方法。有效下降文件資源、IO資源,內存資源的損耗。即使是阿里這種海量數據,高併發場景也可以有效下降端到端延遲,並具有較強的橫向擴展能力。
本文出自:http://jm.taobao.org/2017/01/12/rocketmq-quick-start-in-10-minutes/