RocketMQ是阿里開源的分佈式消息中間件,跟其它中間件相比,RocketMQ的特色是純JAVA實現;集羣和HA實現相對簡單;在發生宕機和其它故障時消息丟失率更低。網絡
先講專業術語的含義,後面會畫流程圖來更好的去理解它們。架構
消息生產者,位於用戶的進程內,Producer經過NameServer獲取全部Broker的路由信息
,根據負載均衡策略選擇將消息發到哪一個Broker,而後調用Broker接口提交消息。負載均衡
生產者組,簡單來講就是多個發送同一類消息的生產者稱之爲一個生產者組。分佈式
消息消費者,位於用戶進程內。Consumer經過NameServer獲取全部broker的路由信息後,向Broker發送Pull請求來獲取消息數據。Consumer能夠以兩種模式啓動,廣播(Broadcast)和集羣(Cluster),廣播模式下,一條消息會發送給全部Consumer,集羣模式下消息只會發送給一個Consumer。ui
消費者組,和生產者相似,消費同一類消息的多個 Consumer 實例組成一個消費者組。.net
Topic用於將消息按主題作劃分,Producer將消息發往指定的Topic,Consumer訂閱該Topic就能夠收到這條消息。Topic跟發送方和消費方都沒有強關聯關係,發送方能夠同時往多個Topic投放消息,消費方也能夠訂閱多個Topic的消息。在RocketMQ中,Topic是一個上邏輯概念。消息存儲不會按Topic分開。3d
表明一條消息,使用MessageId
惟一識別,用戶在發送時能夠設置messageKey,便於以後查詢和跟蹤。一個 Message 必須指定 Topic,至關於寄信的地址。Message 還有一個可選的 Tag 設置,以便消費端能夠基於 Tag 進行過濾消息。也能夠添加額外的鍵值對,例如你須要一個業務 key 來查找 Broker 上的消息,方便在開發過程當中診斷問題。code
標籤能夠被認爲是對 Topic 進一步細化。通常在相同業務模塊中經過引入標籤來標記不一樣用途的消息。server
Broker是RocketMQ的核心模塊,負責接收並存儲消息
,同時提供Push/Pull接口來將消息發送給Consumer。Consumer可選擇從Master或者Slave讀取數據。多個主/從組成Broker集羣,集羣內的Master節點之間不作數據交互。Broker同時提供消息查詢的功能,能夠經過MessageID和MessageKey來查詢消息。Borker會將本身的Topic配置信息實時同步到NameServer。中間件
Topic和Queue是1對多的關係,一個Topic下能夠包含多個Queue,主要用於負載均衡。發送消息時,用戶只指定Topic,Producer會根據Topic的路由信息選擇具體發到哪一個Queue上。Consumer訂閱消息時,會根據負載均衡策略決定訂閱哪些Queue的消息。
RocketMQ在存儲消息時會爲每一個Topic下的每一個Queue生成一個消息的索引文件,每一個Queue都對應一個Offset記錄當前Queue中消息條數。
NameServer能夠看做是RocketMQ的註冊中心,它管理兩部分數據:集羣的Topic-Queue的路由配置;Broker的實時配置信息。其它模塊經過Nameserv提供的接口獲取最新的Topic配置和路由信息。
Producer/Consumer
:經過查詢接口獲取Topic對應的Broker的地址信息Broker
: 註冊配置信息到NameServer, 實時更新Topic信息到NameServer咱們由簡單到複雜的來理解,它的一些核心概念
這個圖很好理解,消息先發到Topic,而後消費者去Topic拿消息。只是Topic在這裏只是個概念,那它究竟是怎麼存儲消息數據的呢,這裏就要引入Broker概念。
Topic是一個邏輯上的概念,實際上Message是在每一個Broker上以Queue的形式記錄。
從上面的圖片能夠總結下幾條結論。
一、消費者發送的Message會在Broker中的Queue隊列中記錄。 二、一個Topic的數據可能會存在多個Broker中。 三、一個Broker存在多個Queue。 四、單個的Queue也可能存儲多個Topic的消息。
也就是說每一個Topic在Broker上會劃分紅幾個邏輯隊列,每一個邏輯隊列保存一部分消息數據,可是保存的消息數據實際上不是真正的消息數據,而是指向commit log的消息索引。
Queue不是真正存儲Message的地方,真正存儲Message的地方是在CommitLog
。
如圖(盜圖)
左邊的是CommitLog。這個是真正存儲消息的地方。RocketMQ全部生產者的消息都是往這一個地方存的。
右邊是ConsumeQueue。這是一個邏輯隊列。和上文中Topic下的Queue是一一對應的。消費者是直接和ConsumeQueue打交道。ConsumeQueue記錄了消費位點,這個消費位點關聯了commitlog的位置。因此即便ConsumeQueue出問題,只要commitlog還在,消息就沒丟,能夠恢復出來。還能夠經過修改消費位點來重放或跳過一些消息。
在部署RocketMQ時,會部署兩種角色。NameServer和Broker。如圖(盜圖)
針對這張圖作個說明
一、Product和consumer集羣部署,是你開發的項目進行集羣部署。 二、Broker 集羣部署是爲了高可用,由於Broker是真正存儲Message的地方,集羣部署是爲了不一臺掛掉,致使整個項目KO.
那Name SerVer是作什麼用呢,它和Product、Consumer、Broker以前存在怎樣的關係呢?
先簡單歸納Name Server的特色
一、Name Server是一個幾乎無狀態節點,可集羣部署,節點之間無任何信息同步。 二、每一個Broker與Name Server集羣中的全部節點創建長鏈接,定時註冊Topic信息到全部Name Server。 三、Producer與Name Server集羣中的其中一個節點(隨機選擇)創建長鏈接,按期從Name Server取Topic路由信息。 四、Consumer與Name Server集羣中的其中一個節點(隨機選擇)創建長鏈接,按期從Name Server取Topic路由信息。
這裏面最核心的是每一個Broker與Name Server集羣中的全部節點創建長鏈接
這樣作好處多多。
一、這樣可使Name Server之間能夠沒有任何關聯,由於它們綁定的Broker是一致的。
二、做爲Producer或者Consumer能夠綁定任何一個Name Server 由於它們都是同樣的。
1)鏈接 單個Broker和全部Name Server保持長鏈接。
2)心跳
心跳間隔:每隔30秒向全部NameServer發送心跳,心跳包含了自身的Topic配置信息。
心跳超時:NameServer每隔10秒,掃描全部還存活的Broker鏈接,若某個鏈接2分鐘內沒有發送心跳數據,則斷開鏈接。
3)斷開 :當Broker掛掉;NameServer會根據心跳超時主動關閉鏈接,一旦鏈接斷開,會更新Topic與隊列的對應關係,但不會通知生產者和消費者。
一個Topic分佈在多個Broker上,一個Broker能夠配置多個Topic,它們是多對多的關係。
若是某個Topic消息量很大,應該給它多配置幾個Queue,而且儘可能多分佈在不一樣Broker上,減輕某個Broker的壓力。
因爲消息分佈在各個Broker上,一旦某個Broker宕機,則該Broker上的消息讀寫都會受到影響。
因此RocketMQ提供了Master/Slave的結構,Salve定時從Master同步數據,若是Master宕機,則Slave提供消費服務,可是不能寫入消息,此過程對應用透明,由RocketMQ內部解決。
有兩個關鍵點:
思考1
一旦某個broker master宕機,生產者和消費者多久才能發現?
受限於Rocketmq的網絡鏈接機制,默認狀況下最多須要30秒,由於消費者每隔30秒從nameserver獲取全部topic的最新隊列狀況,這意味着某個broker若是宕機,客戶端最多要30秒才能感知。
思考2
master恢復恢復後,消息可否恢復。
消費者獲得Master宕機通知後,轉向Slave消費,可是Slave不能保證Master的消息100%都同步過來了,所以會有少許的消息丟失。可是消息最終不會丟的,一旦Master恢復,未同步過去的消息會被消費掉。
1)鏈接 : 單個Consumer和一臺NameServer保持長鏈接,若是該NameServer掛掉,消費者會自動鏈接下一個NameServer,直到有可用鏈接爲止,並能自動重連。
2)心跳: 與NameServer沒有心跳
3)輪詢時間 : 默認狀況下,消費者每隔30秒從NameServer獲取全部Topic的最新隊列狀況,這意味着某個Broker若是宕機,客戶端最多要30秒才能感知。
1)鏈接 :單個消費者和該消費者關聯的全部broker保持長鏈接。
集羣消費模式下,一個消費者集羣多臺機器共同消費一個Topic的多個隊列,一個隊列只會被一個消費者消費。若是某個消費者掛掉,分組內其它消費者會接替掛掉的消費者繼續消費。
1)鏈接 單個Producer和一臺NameServer保持長鏈接,若是該NameServer掛掉,生產者會自動鏈接下一個NameServer,直到有可用鏈接爲止,並能自動重連。
2)輪詢時間 默認狀況下,生產者每隔30秒從NameServer獲取全部Topic的最新隊列狀況,這意味着某個Broker若是宕機,生產者最多要30秒才能感知,在此期間,
發往該broker的消息發送失敗。
3)心跳 與nameserver沒有心跳
鏈接 單個生產者和該生產者關聯的全部broker保持長鏈接。
二、RocketMQ nameserver、broker之間的關係
只要本身變優秀了,其餘的事情纔會跟着好起來(中將8)