1、發展歷程
早期淘寶內部有兩套消息中間件系統:Notify和Napoli。 先有的Notify(至今12歷史),後來因有序場景需求,且剛好當時Kafka開源(2011年),因此參照Kafka的設計理念自研了RocketMQ。 目前Notify和RocketMQ兩者的定位以下:html
- RocketQ 主要面向消息有序的場景,可以提供更大的消息堆積能力,拉模式,消息持久化在磁盤
- Notify主要面向更加安全可靠地交易類場景,無序、推模式、消息持久化在mysql
RocketMQ發展歷程以下:java
- Metaq 1.x 開源社區維護killme2008維護,由於依賴zk掛了,致使上下游服務全網宕機,到了12年基於開源Kafka,直接用java語言翻譯重寫
- Metaq 2.x 2012年11月上線,淘寶內部使用
- RocketMQ 3.x 後來一統江湖成爲整個阿里系主流MQ。基於公司內部開源共建原則, RocketMQ項目只維護核心功能,且去除了全部其餘運行時依賴,核心功能最簡化。每一個BU的個性化需求都在RocketMQ項目之上進行深度定製。RocketMQ向其餘BU提供的僅僅是Jar包,例如要定製一個Broker,那麼只須要依賴rocketmq-broker這個jar包便可,可經過API進行交互,若是定製client,則依賴rocketmq-client這個jar包,對其提供的api進行再封裝。
- RocketMQ 4.x.x 捐獻給Apache社區,通過一年時間重構孵化成爲頂級項目
Metaq更名爲RocketMQ,RocketMQ項目作核心功能,淘寶內部其餘個性化需求有作定製化開發,如:
com.taobao.metaq v3.0 (爲淘寶應用提供消息服務 ) com.alipay.zpullmsg v1.0 (爲支付寶應用提供消息服務) com.alibaba.commonmq v1.0 (爲 B2B 應用提供消息服務)mysql
RocketMQ一共經歷了三代里程碑演進:sql
- Notify 爲阿里系第一代MQ產品。推模式,數據存儲採用關係型數據庫。
- Metaq 爲阿里系第二代MQ產品。拉模式,自研的專有消息存儲,在日誌處理方面參考Kafka,典型表明MetaQ。
- RocketMQ爲阿里系第三代MQ產品。以拉模式爲主,兼有推模式,低延遲消息引擎RocketMQ,在二代功能特性的基礎上,爲電商金融領域添加了可靠重試、基於文件存儲的分佈式事務等特性。使用在了阿里大量的應用上,典型如雙11場景,具備萬億級消息堆積能力。
RocketMQ項目根據開源與商業分紅2個版本:docker
- Apache RocketMQ開源版
- 2013年,阿里雲ONS(功能相比較更齊全,特別是運維體系完善,例如:運維管控,安全受權,深度培訓等歸入商業重中之重)
- 2015年,Aliware MQ(Message Queue)是RocketMQ的商業版本,是阿里雲商用的專業消息中間件,是企業級互聯網架構的核心產品,基於高可用分佈式集羣技術,搭建了包括髮布訂閱、消息軌跡、資源統計、定時(延時)、監控報警等一套完整的消息雲服務。
RocketMQ項目根據開源與商業分紅2個版本:數據庫
- Apache RocketMQ是對外開源版
- 2013年,阿里雲ONS(功能相比較更齊全,特別是運維體系完善,例如:運維管控,安全受權,深度培訓等歸入商業重中之重)
- 2015年,Aliware MQ(Message Queue)是RocketMQ的商業版本,是阿里雲商用的專業消息中間件,是企業級互聯網架構的核心產品,基於高可用分佈式集羣技術,搭建了包括髮布訂閱、消息軌跡、資源統計、定時(延時)、監控報警等一套完整的消息雲服務。
2、系統架構
系統定位
- 是一個隊列模型的消息中間件,具備高性能、高可靠、高實時、分佈式特色
- 同時支持Push與Pull方式消費消息
- 能支撐天貓雙十一海量消息考驗
- 可以保證嚴格的消息順序
- 提供豐富的消息拉取模式
- 高效的訂閱者水平擴展能力
- 億級消息堆積能力
四種集羣部署方式:
- 單master (缺點:broker宕機,服務不可用)
- 多master無slave (缺點:單臺機器宕機期間,這臺機器上未被消費的消息在機器恢復以前不可訂閱)
- 多master多slave,異步複製 (缺點:Master 宕機,磁盤損壞狀況,可能會丟失少許消息)
- 多master多slave,同步雙寫(缺點:性能比異步複製模式略低,大約低 10%左右)
生產環境部署都是多主多從。下面以2主2從爲例api
組件角色
3、關鍵特性
1.單機支持1萬以上持久化隊列服務器
- 順序寫,隨機讀。 consumerQueue是邏輯隊列存儲元數據信息,commitlog負責存儲消息,consumerQueue只存儲消息在commitlog中的位置信息,定長存儲,支持串行方式刷盤。
2.刷盤策略數據結構
兩者的區別在因而寫完PageCache直接返回,仍是刷盤後返回
3.消息查詢/消息回溯
- 支持MessageID和MessageKey查詢。(業務場景:如某個訂單處理失敗,是消息沒收到仍是收處處理出錯了)
- 按照時間來回溯消息,精度毫秒。(業務場景:訂單分析,程序bug,致使今天從某個時間點的消息須要從新開始消費)
4.消息過濾
- Broker端(tag的哈希值比對,丟到對應的consumeQueue中) consumer端(直接和tag比)
5.消息獲取機制
本質上都是Pull機制(據官方資料顯示其中PushConsumer的實時性接近於push)。
- PushConsumer: consumer經過長輪詢拉取消息後回調MessageListener接口完成消費,業務只須要完成MessageListener完成業務邏輯便可。(註冊監聽回調,一個線程專門長輪訓從broker端拉消息,push到一個本地可配置隊列)輯便可。(註冊監聽回調,一個線程專門長輪訓從broker端拉消息,push到一個本地可配置隊列)
- PullConsumer: 徹底由業務系統去控制,定時拉取消息,指定隊列消費,主要由業務控制。
6.單隊列並行消費
- 單隊列一批消息拉取到消費端,既能夠支持單線程串行有序消費,也能夠支持多線程亂序消費提升併發性能,以下圖所示:
採用滑動窗口方式並行消費,多個線程消費,提交offset都是最小offset。
7.消費負載均衡
都在客戶端實現
Producer端:從NameServer獲取MessageQueue列表,RR選擇具體的消息隊列發送消息。
Consumer端: 從NameServer獲取MessageQueue列表和其餘Consumer狀態信息,達到平均消費目的(consumer超過隊列數則處於空閒狀態)
8.順序消息原理
在RocketMQ中,主要指的是局部順序,即一類消息爲知足順序性,必須 Producer 單線程順序發送,且發送到同一個隊列,這樣 Consumer 就能夠按照 Producer 發送 的順序去消費消息。
- 普通順序消息:Broker重啓,隊列總數發生變化,致使哈希取模後定位隊列變化,致使短暫消息順序不一致。
- 嚴格順序消息:只要一臺機器不可用,整個集羣不可用。(同步雙寫保證)
9.事務支持
RocketMQ採用了2PC的方案來提交事務消息,同時增長一個補償邏輯來處理二階段超時或者失敗的消息,以下圖所示:
上圖說明了事務消息的大體方案,分爲兩個邏輯:正常事務消息的發送及提交、事務消息的補償流程
事務消息發送及提交:
- 發送消息(half消息)
- 服務端響應消息寫入結果
- 根據發送結果執行本地事務(若是寫入失敗,此時half消息對業務不可見,本地邏輯不執行)
- 根據本地事務狀態執行Commit或者Rollback(Commit操做生成消息索引,消息對消費者可見)
補償流程:
- 對沒有Commit/Rollback的事務消息(pending狀態的消息),從服務端發起一次「回查」
- Producer收到回查消息,檢查回查消息對應的本地事務的狀態
- 根據本地事務狀態,從新Commit或者Rollback
- 補償階段用於解決消息Commit或者Rollback發生超時或者失敗的狀況。
10.延時消息
業務場景:支付曾經提過延時消費需求(對應消費失敗後,延時多久再推送)
開源版本RocketMQ僅支持定時Level(幾個梯度的延時,5s、10s、1min等) 阿里雲的ONS支持定時level,以及制定毫秒級別延時時間
11.消息失敗重試
Producer 的 send 方法自己支持內部重試,重試邏輯以下:
(1) 至多重試 3 次
(2) 若是發送失敗,則輪轉到下一個 Broker
(3) 這個方法的總耗時時間不超過 sendMsgTimeout設置的值,默認 10s因此,若是自己向 broker 發送消息產生超時異常,就不會再作重試。 再發送失敗由應用層本身作。
- Consumer端:
廣播模式:發送失敗的消息丟棄, 廣播模式對於失敗重試代價太高,對整個集羣性能會有較大影響,失敗重試功能交由應用處理 集羣模式:將消費失敗的消息一條條的發送到broker的重試隊列中去,若是此時依然有發送到重試隊列仍是失敗的消息,那就在cosumer的本地線 程
定時5秒鐘之後重試從新消費消息,再走一次上面的消費流程。
12.Broker HA機制
- 同步雙寫:HA 採用同步雙寫方式,主備都寫成功,嚮應用返回成功。
- 異步複製:slave啓動一個線程,不斷從master拉取commitlog中的數據,而後異步build出ConsumeQueue數據結構。
13.死信隊列
因爲某些緣由消息沒法被正確的投遞,爲了確保消息不會被無端的丟棄,通常將其置於一個特殊角色的隊列,這個隊列通常稱之爲死信隊列。與此對應的還有一個「回退隊列」的概念,試想若是消費者在消費時發生了異常,那麼就不會對這一次消費進行確認(Ack), 進而發生回滾消息的操做以後消息始終會放在隊列的頂部,而後不斷被處理和回滾,致使隊列陷入死循環。爲了解決這個問題,能夠爲每一個隊列設置一個回退隊列,它和死信隊列都是爲異常的處理提供的一種機制保障。實際狀況下,回退隊列的角色能夠由死信隊列和重試隊列來扮演。
14.重試隊列
重試隊列其實能夠當作是一種回退隊列,具體指消費端消費消息失敗時,爲防止消息無端丟失而從新將消息回滾到 Broker 中。與回退隊列不一樣的是重試隊列通常分紅多個重試等級,每一個重試等級通常也會設置從新投遞延時,重試次數越多投遞延時就越大。舉個例子:消息第一次消費失敗入重試隊列 Q1,Q1 的從新投遞延遲爲 5s,在 5s 事後從新投遞該消息;若是消息再次消費失敗則入重試隊列 Q2,Q2 的從新投遞延遲爲 10s,在 10s 事後再次投遞該消息。以此類推,重試越屢次從新投遞的時間就越久,爲此須要設置一個上限,超過投遞次數就入死信隊列。重試隊列與延遲隊列有相同的地方,都是須要設置延遲級別,它們彼此的區別是:延遲隊列動做由內部觸發,重試隊列動做由外部消費端觸發;延遲隊列做用一次,而重試隊列的做用範圍會向後傳遞。
4、不足之處
RocketMQ無論系統架構,仍是底層存儲都有居多亮點,以此來支撐強大的各類特性,不能否認也有居多不足之處:
- 不支持Master/Slave自動切換。RocketMQ開源版本目前還不支持把Slave自動轉成Master,若是機器資源不足,須要把Slave轉成Master,則要手動中止Slave角色的Broker,更改配置文件,用新的配置文件啓動Broker。商業版本支持自動master/slave主從切換
- 不支持數據遷移,對服務擴容不太友好,也不靈活。若是服務須要擴容,只能增長服務器節點數了,而後新增queue分配到新節點上。若是新老機器負載不均衡,要麼多增長queue到新機器上,要麼替換性能不強的老舊機器
- 不支持多掛載點。當今硬件發展突飛猛進,pc服務器性能愈來愈強大,一個物理機器會掛載很塊多磁盤,但一個RocketMQ實例卻只能讀寫操做一個掛載點數據,想榨乾機器資源,操做多掛載點須要部署多實例或依靠docker容器等來實現
博客地址引用:http://www.javashuo.com/article/p-zxhfrkhi-dw.html