Apache RocketMQ 基礎概念及架構解析

1.png

Apache RocketMQ 基礎概念及架構解析

Apache RocketMQ 系列:

Apache RocketMQ之JMS基本概念及使用:http://www.lxweimin.com/p/d2e3fd77c4f4
Apache RocketMQ 基礎概念及架構解析:http://www.lxweimin.com/p/95ab928960b3
Apache RocketMQ 的基礎特性介紹:http://www.lxweimin.com/p/570680b32590
Apache RocketMQ 集群搭建(兩主兩從):http://www.lxweimin.com/p/b090138cf52c
Apache RocketMQ 刷盤策略與復制策略: http://www.lxweimin.com/p/d66b381428bb

優秀博客:
https://blog.csdn.net/BtB5e6Nsu1g511Eg5XEg/article/details/83828893
https://blog.csdn.net/GV7lZB0y87u7C/article/details/78382605
https://blog.csdn.net/qq_34021712/article/details/78169014
https://blog.csdn.net/babyupup/article/details/72642571
http://www.lxweimin.com/p/f90b0f175e2d


本文主要介紹:

一、RocketMQ起源

二、RocketMQ的概念模型

三、RocketMQ的存儲模型

四、RocketMQ的部署模型

五、RocketMQ最佳實踐總結 (后面介紹)


一、RocketMQ的起源

通常,每個產品的誕生都源于一個具體的需求或問題,RocketMQ也不例外。起初,產品的原型像一個巨石,把所有需要實現的程序和接口都羅列到一起。但隨著公司業務的發展,所有的系統和功能都在這個巨石上開發,當覆蓋幾百上千名開發人員的時候,瓶頸就出來了。這時候,就需要我們把系統進行分解。

1.png

分解后,就出現了上圖中的分布式架構,這類架構最大的特點就是解耦,而RocketMQ的異步解耦意味著底層的重構不會影響到上層應用的功能。RocketMQ另一個優勢是削峰填谷,在面臨流量的不確定性時,實現對流量的緩沖處理。此外,RocketMQ的順序設計特性使得RocketMQ成為一個天然的排隊引擎,例如,三個應用同時對一個后臺引擎發起請求,排隊引擎的特性可以確保不會引起“撞車”事故。

總結:RocketMQ的作用(消息中間件):解耦、削峰填谷、高并發,或者說:異步消息處理、高性能(高并發讀寫)、高可用(主備)、可伸縮(削峰填谷)、最終一致性。

補充:

在2007年的時候,淘寶實施了“五彩石”項目,“五彩石”用于將交易系統從單機變成分布式,也是在這個過程中產生了阿里巴巴第一代消息引擎——Notify。

在2010年的時候,阿里巴巴B2B部門基于ActiveMQ的5.1版本也開發了自己的一款消息引擎,稱為Napoli,這款消息引擎在B2B里面廣泛地被使用,不僅僅是在交易領域,在很多的后臺異步解耦等方面也得到了廣泛的應用。

在2011年的時候,業界出現了現在被很多大數據領域所推崇的Kafka消息引擎,阿里巴巴在研究了Kafka的整體機制和架構設計之后,基于Kafka的設計使用Java進行了完全重寫并推出了MetaQ 1.0版本,主要是用于解決順序消息和海量堆積的問題。

在2012年,阿里巴巴對于MetaQ進行了架構重組升級,開發出了MetaQ 2.0,這時就發現MetaQ原本基于Kafka的架構在阿里巴巴如此龐大的體系下很難進行水平擴展,所以在2012年的時候就開發了RocketMQ 3.0版本。很多人會問到RocketMQ 3.0和MetaQ 3.0的區別,其實這兩者是等價的版本,只不過阿里內部使用的稱為MetaQ 3.0,外部開源稱之為RocketMQ 3.0。

在2015年,又基于RocketMQ開發了阿里云上的Aliware MQ和Notify 3.0。

在2016年的時候,阿里巴巴將RocketMQ的內核引擎捐贈給了Apache基金會。

以上就是RocketMQ的整體發展歷史,其實在阿里巴巴內部圍繞著RocketMQ內核打造了三款產品,分別是MetaQ、Notify和Aliware MQ。這三者分別采用了不同的模型,MetaQ主要使用了拉模型,解決了順序消息和海量堆積問題;Notify主要使用了推模型,解決了事務消息;而云產品Aliware MQ則是提供了商業化的版本。


二、RocketMQ的概念模型

對于任何一款中間件產品而言,清晰的概念模型是幫助開發者正確理解使用它的關鍵。從RocketMQ的概念模型來看:Topic是用于存儲邏輯的地址的,Producer是信息的發送,Consumer是信息的接收者。

2.png

這只是一個基礎的概念模型,在實際的生產中,結構會更復雜,例如我們需要對中間的Topic進行分區,出現多個有關聯的Topic,再如同一個信息的發送方會有多個訂閱者,同一個需求方會有多個發送方,出現一對多、多對一的情況。

3.png

上圖就是對Topic、Producer、Consumer擴展后的概念模型。RocketMQ中可以接觸到的所有概念都可以在這個概念模型圖中找到。

左邊有兩個Producer,中間就是兩個分布式的Topic,用于存儲邏輯地址的兩個Topic中分別有兩個用于存儲物理存儲地址的Message Queue,Broker是實際部署過程的對應的一臺設備,右邊則是兩個Consumer,Consumer Group是代表兩個Consumer可共享相互之間的訂閱。不同的Consumer Group相互獨立。

一句話總結就是不同的Group是廣播訂閱的,同一個Group則是負載訂閱的。圖中的連線表示各模塊之間的關系,例如Consumer Group A中的Consumer1對應著Message Queue0和Message Queue1的兩個隊列,分布在BrokerA這一臺設備上。

補充:

Producer Group:
用來表示一個収送消息應用,一個 Producer Group 下包含多個 Producer 實例,可以是多臺機器,也可以 是一臺機器的多個迕程,戒者一個迕程的多個 Producer 對象。一個 Producer Group 可以収送多個 Topic 消息,Producer Group 作用如下:

  1. 標識一類 Producer
  2. 可以通過運維工具查詢返個収送消息應用下有多個 Producer 實例
  3. 収送分布式事務消息時,如果 Producer 中途意外宕機,Broker 會主勱回調 Producer Group 內的任意一臺機器來確訃事務狀態

Consumer Group:
用來表示一個消費消息應用,一個 Consumer Group 下包含多個 Consumer 實例,可以是多臺機器,也可
以是多個迕程,戒者是一個迕程的多個 Consumer 對象。一個 Consumer Group 下的多個 Consumer 以均攤
方式消費消息,如果設置為廣播方式,那舉返個 Consumer Group 下的每個實例都消費全量數據。

Topoic:消息的邏輯管理單位。

Message Queue:消息的物理管理單位。一個Topic下可以有多個Queue,Queue的引入使得消息存儲可以分布式集群化,具有了水平擴展的能力。

順序消息:用戶實現MessageQueueSelector為某一批消息(通常是有同樣的唯一的標示ID),選擇同一個Queue,則這一批消息的消費將是順序消費(并由同一個consumer完成消費)。

事務消息:這樣的消息有多個狀態,并且其發送是兩階段的。第一個階段發送PREPARED狀態的消息,此時consumer是看不見這種狀態的消息的,發送完畢后回調用戶的TransactionExecutor接口,執行相應的事務操作(如數據庫),當事務操作成功時,則對此條消息返回commit,讓broker對該消息執行commit操作,成為commit狀態的消息對consumer是可見的。


三、RocketMQ的存儲模

RocketMQ的消息的存儲是由ConsumeQueue和CommitLog 配合來完成的,ConsumeQueue中只存儲很少的數據,消息主體都是通過CommitLog來進行讀寫。

4.png
CommitLog:

是消息主體以及元數據的存儲主體,對CommitLog建立一個ConsumeQueue,每個ConsumeQueue對應一個(概念模型中的)MessageQueue,所以只要有Commit Log在,Consume Queue即使數據丟失,仍然可以恢復出來。

Consume Queue:

是一個消息的邏輯隊列,存儲了這個Queue在CommitLog中的起始offset,log大小和MessageTag的hashCode。每個Topic下的每個Queue都有一個對應的ConsumerQueue文件,例如Topic中有三個隊列,每個隊列中的消息索引都會有一個編號,編號從0開始,往上遞增。并由此一個位點offset的概念,有了這個概念,就可以對Consumer端的消費情況進行隊列定義。

補充:

RocketMQ的broker端,不負責推送消息,無論消費者是否消費消息,都將消息存儲起來。誰要消費消息,就向broker發請求獲取消息,消費記錄由consumer來維護。RocketMQ提供了兩種存儲方式來保留消費記錄:一種是保留在consumer所在的服務器上;另一種是保存在broker服務器上。用戶還可以自己實現相應的消費進度存儲接口。

默認情況下,采用集群消費(CLUSTERING),會將記錄保存在broker端;而采用廣播消費(BROADCASTING)則會將消費記錄保存在本地。

RocketMQ以Topic來管理不同應用的消息。對于生產者而言,發送消息是,需要指定消息的Topic,對于消費者而言,在啟動后,需要訂閱相應的Topic,然后可以消費相應的消息。Topic是邏輯上的概念,在物理實現上,一個Topic由多個Queue組成,采用多個Queue的好處是可以將Broker存儲分布式化,提高系統性能。

RocketMQ中,producer將消息發送給Broker時,需要制定發送到哪一個隊列中,默認情況下,producer會輪詢的將消息發送到每個隊列中(所有broker下的Queue合并成一個List去輪詢)。

對于consumer而言,會為每個consumer分配固定的隊列(如果隊列總數沒有發生變化),consumer從固定的隊列中去拉取沒有消費的消息進行處理。

RocketMQ 存儲特點:

零拷貝原理:Consumer 消費消息過程,使用了零拷貝,零拷貝包含以下兩種方式:

  1. 使用 mmap + write 方式

優點:即使頻繁調用,使用小塊文件傳輸,效率也很高

缺點:不能很好的利用 DMA 方式,會比 sendfile 多消耗CPU,內存安全性控制復雜,需要避免 JVM Crash 問題。

  1. 使用 sendfile 方式

優點:可以利用 DMA 方式,消耗 CPU 較少,大塊文件傳輸效率高,無內存安全新問題。

缺點:小塊文件效率低亍 mmap 方式,只能是 BIO 方式傳輸,不能使用 NIO。

RocketMQ 選擇了第一種方式,mmap+write 方式,因為有小塊數據傳輸的需求,效果會比 sendfile 更好。

RocketMQ 文件系統:

RocketMQ 選擇 Linux Ext4 文件系統。

原因如下:
Ext4 文件系統刪除 1G 大小的文件通常耗時小亍 50ms,而 Ext3 文件系統耗時約 1s 左右,且刪除文件時,磁盤 IO 壓力極大,會導致 IO 寫入超時。

文件系統局面需要做以下調優措施: 文件系統 IO 調度算法需要調整為 deadline,因為 deadline 算法在隨機讀情況下,可以合幵讀請求為順序跳躍
方式,從而提高讀 IO 吞吐量。

RocketMQ 數據存儲結構:
5.png
RocketMQ 存儲目錄結構
|-- abort 
|-- checkpoint 
|-- config
| |-- consumerOffset.json
| |-- consumerOffset.json.bak
| |-- delayOffset.json
| |-- delayOffset.json.bak
| |-- subscriptionGroup.json.bak
| |-- topics.json
| |-- topics.json.bak 
|-- commitlog
| |-- 00000003384434229248
| |-- 000000033855079710
| |-- 0000000338658171289
|-- consumequeue
  |-- %DLQ%ConsumerGroupA
  | |-- 0
  | | |-- 00000000000006000000
  |-- %RETRY%ConsumerGroupA
  | |-- 0
  | | |-- 00000000000000000000
  |-- %RETRY%ConsumerGroupB
  | |-- 0
  | | |-- 00000000000000000000
  |-- SCHEDULE_TOPIC_XXXX
  | |-- 2
  | | |-- 00000000000006000000
  | |-- 3
  | | |-- 00000000000006000000
  |-- TopicA
  | |-- 0
  | | |-- 00000000002604000000
  | | |-- 00000000002610000000
  | | |-- 00000000002616000000
  | |-- 1
  | | |-- 00000000002610000000
  | | |-- 00000000002610000000
  |-- TopicB
  | |-- 0
  | | |-- 00000000000732000000
  | |-- 1
  | | |-- 00000000000732000000
  | |-- 2
  | | |-- 00000000000732000000

四、RocketMQ的部署模型

在實際的部署過程中,Broker是實際存儲消息的數據節點,Nameserver則是服務發現節點,Producer發送消息到某一個Topic,并給到某個Consumer用于消費的過程中,需要先請求Nameserver拿到這個Topic的路由信息,即Topic在哪些Broker上有,每個Broker上有哪些隊列,拿到這些請求后再把消息發送到Broker中;相對的,Consumer在消費的時候,也會經歷這個流程。

6.png

補充:

NameServer:

NameServer是一個幾乎無狀態節點,可集群部署,節點之間無任何信息同步(類似ZK)。

NameServer用于存儲Topic、Broker關系信息,功能簡單,穩定性高。多個NameServer之間相互沒有通信,單臺NameServer宕機不影響其他NameServer與集群;即使整個NameServer集群宕機,已經正常工作的Producer,Consumer,Broker仍然能正常工作,但新起的Producer, Consumer,Broker就無法工作。

NameServer壓力不會太大,平時主要開銷是在維持心跳和提供Topic-Broker的關系數據。但有一點需要注意,Broker向NameServer發心跳時,會帶上當前自己所負責的所有Topic信息,如果Topic個數太多(萬級別),會導致一次心跳中,就Topic的數據就幾十M,網絡情況差的話,網絡傳輸失敗,心跳失敗,導致NameServer誤認為Broker心跳失敗。

Broker :

Broker 部署相對復雜,Broker分為Master 與 Slave,一個Master可以對應多個 Slave,但是一個Slave只能對應一個Master。

Master 與 Slave 的對應關系通過指定相同的BrokerName,不同的 BrokerId 來定義,BrokerId為0表示Master,非 0 表示 Slave。

Master可以部署多個。每個Broker與NameServer 集群中的所有節點建立長連接,定時注冊Topic信息到所有NameServer。

Producer與NameServer集群中的其中一個節點(隨機選擇)建立長連接,定期從 Name Server 取 Topic 路由信息,并向提供 Topic 服務的 Master 建立長連接,且定時向 Master 發送心跳。

Producer :

Producer 完全無狀態,可集群部署。

Producer啟動時,也需要指定NameServer的地址,從NameServer集群中選一臺建立長連接。如果該NameServer宕機,會自動連其他NameServer。直到有可用的NameServer為止。

Producer每30秒從NameServer獲取Topic跟Broker的映射關系,更新到本地內存中。再跟Topic涉及的所有Broker建立長連接,每隔30秒發一次心跳。在Broker端也會每10秒掃描一次當前注冊的Producer,如果發現某個Producer超過2分鐘都沒有發心跳,則斷開連接。

Producer發送時,會自動輪詢當前所有可發送的broker,一條消息發送成功,下次換另外一個broker發送,以達到消息平均落到所有的broker上。

假如某個Broker宕機,意味生產者最長需要30秒才能感知到。在這期間會向宕機的Broker發送消息。當一條消息發送到某個Broker失敗后,會往該broker自動再重發2次,假如還是發送失敗,則拋出發送失敗異常。業務捕獲異常,重新發送即可。客戶端里會自動輪詢另外一個Broker重新發送,這個對于用戶是透明的。

Consumer:

Consumer與NameServer集群中的其中一個節點(隨機選擇)建立長連接,定期從NameServer取Topic路由信息,并向提供Topic服務的Master、Slave建立長連接,且定時向 Master、Slave發送心跳。

Consumer既可以從Master訂閱消息,也可以從 Slave 訂閱消息,訂閱規則由 Broker 配置決定。

Consumer啟動時需要指定NameServer地址,與其中一個NameServer建立長連接。消費者每隔30秒從NameServer獲取所有Topic的最新隊列情況,這意味著某個Broker如果宕機,客戶端最多要30秒才能感知。連接建立后,從NameServer中獲取當前消費Topic所涉及的Broker,直連Broker。

Consumer跟Broker是長連接,會每隔30秒發心跳信息到Broker。Broker端每10秒檢查一次當前存活的Consumer,若發現某個Consumer 2分鐘內沒有心跳,就斷開與該Consumer的連接,并且向該消費組的其他實例發送通知,觸發該Consumer集群的負載均衡。

Consumer有兩種模式消費:集群消費,廣播消費。

廣播消費:每個消費者消費Topic下的所有隊列。

集群消費:一個topic可以由同一個ID下所有消費者分擔消費。


五、RocketMQ最佳實踐總結

Apache RocketMQ 集群搭建(兩主兩從):http://www.lxweimin.com/p/b090138cf52c


如有問題,請留言:)。
如需轉載,請注明出處:)。
感覺有幫助,可以點下喜歡:)。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,316評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,481評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,241評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,939評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,697評論 6 409
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,182評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,247評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,406評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,933評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,772評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,973評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,516評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,638評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,866評論 1 285
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,644評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,953評論 2 373

推薦閱讀更多精彩內容