RocketMQ(1)-架構原理
RocketMQ是阿里開源的分散式訊息中介軟體,跟其它中介軟體相比,RocketMQ的特點是純JAVA實現;叢集和HA實現相對簡單;在發生當機和其它故障時訊息丟失率更低。
一、RocketMQ專業術語
先講專業術語的含義,後面會畫流程圖來更好的去理解它們。
Producer
訊息生產者,位於使用者的程式內,Producer通過NameServer獲取所有Broker的路由資訊
,根據負載均衡策略選擇將訊息發到哪個Broker,然後呼叫Broker介面提交訊息。
Producer Group
生產者組,簡單來說就是多個傳送同一類訊息的生產者稱之為一個生產者組。
Consumer
訊息消費者,位於使用者程式內。Consumer通過NameServer獲取所有broker的路由資訊後,向Broker傳送Pull請求來獲取訊息資料。Consumer可以以兩種模式啟動,廣播(Broadcast)和叢集(Cluster),廣播模式下,一條訊息會傳送給所有Consumer,叢集模式下訊息只會傳送給一個Consumer。
Consumer Group
消費者組,和生產者類似,消費同一類訊息的多個 Consumer 例項組成一個消費者組。
Topic
Topic用於將訊息按主題做劃分,Producer將訊息發往指定的Topic,Consumer訂閱該Topic就可以收到這條訊息。Topic跟傳送方和消費方都沒有強關聯關係,傳送方可以同時往多個Topic投放訊息,消費方也可以訂閱多個Topic的訊息。在RocketMQ中,Topic是一個上邏輯概念。訊息儲存不會按Topic分開。
Message
代表一條訊息,使用MessageId
唯一識別,使用者在傳送時可以設定messageKey,便於之後查詢和跟蹤。一個 Message 必須指定 Topic,相當於寄信的地址。Message 還有一個可選的 Tag 設定,以便消費端可以基於 Tag 進行過濾訊息。也可以新增額外的鍵值對,例如你需要一個業務 key 來查詢 Broker 上的訊息,方便在開發過程中診斷問題。
Tag
標籤可以被認為是對 Topic 進一步細化。一般在相同業務模組中通過引入標籤來標記不同用途的訊息。
Broker
Broker是RocketMQ的核心模組,負責接收並儲存訊息
,同時提供Push/Pull介面來將訊息傳送給Consumer。Consumer可選擇從Master或者Slave讀取資料。多個主/從組成Broker叢集,叢集內的Master節點之間不做資料互動。Broker同時提供訊息查詢的功能,可以通過MessageID和MessageKey來查詢訊息。Borker會將自己的Topic配置資訊實時同步到NameServer。
Queue
Topic和Queue是1對多的關係,一個Topic下可以包含多個Queue,主要用於負載均衡。傳送訊息時,使用者只指定Topic,Producer會根據Topic的路由資訊選擇具體發到哪個Queue上。Consumer訂閱訊息時,會根據負載均衡策略決定訂閱哪些Queue的訊息。
Offset
RocketMQ在儲存訊息時會為每個Topic下的每個Queue生成一個訊息的索引檔案,每個Queue都對應一個Offset記錄當前Queue中訊息條數。
NameServer
NameServer可以看作是RocketMQ的註冊中心,它管理兩部分資料:叢集的Topic-Queue的路由配置;Broker的實時配置資訊。其它模組通過Nameserv提供的介面獲取最新的Topic配置和路由資訊。
Producer/Consumer
:通過查詢介面獲取Topic對應的Broker的地址資訊Broker
: 註冊配置資訊到NameServer, 實時更新Topic資訊到NameServer
二、流程圖
我們由簡單到複雜的來理解,它的一些核心概念
這個圖很好理解,訊息先發到Topic,然後消費者去Topic拿訊息。只是Topic在這裡只是個概念,那它到底是怎麼儲存訊息資料的呢,這裡就要引入Broker概念。
2、Topic的儲存
Topic是一個邏輯上的概念,實際上Message是在每個Broker上以Queue的形式記錄。
從上面的圖片可以總結下幾條結論。
1、消費者傳送的Message會在Broker中的Queue佇列中記錄。
2、一個Topic的資料可能會存在多個Broker中。
3、一個Broker存在多個Queue。
4、單個的Queue也可能儲存多個Topic的訊息。
也就是說每個Topic在Broker上會劃分成幾個邏輯佇列,每個邏輯佇列儲存一部分訊息資料,但是儲存的訊息資料實際上不是真正的訊息資料,而是指向commit log的訊息索引。
Queue不是真正儲存Message的地方,真正儲存Message的地方是在CommitLog
。
如圖(盜圖)
左邊的是CommitLog。這個是真正儲存訊息的地方。RocketMQ所有生產者的訊息都是往這一個地方存的。
右邊是ConsumeQueue。這是一個邏輯佇列。和上文中Topic下的Queue是一一對應的。消費者是直接和ConsumeQueue打交道。ConsumeQueue記錄了消費位點,這個消費位點關聯了commitlog的位置。所以即使ConsumeQueue出問題,只要commitlog還在,訊息就沒丟,可以恢復出來。還可以通過修改消費位點來重放或跳過一些訊息。
3、部署模型
在部署RocketMQ時,會部署兩種角色。NameServer和Broker。如圖(盜圖)
針對這張圖做個說明
1、Product和consumer叢集部署,是你開發的專案進行叢集部署。
2、Broker 叢集部署是為了高可用,因為Broker是真正儲存Message的地方,叢集部署是為了避免一臺掛掉,導致整個專案KO.
那Name SerVer是做什麼用呢,它和Product、Consumer、Broker之前存在怎樣的關係呢?
先簡單概括Name Server的特點
1、Name Server是一個幾乎無狀態節點,可叢集部署,節點之間無任何資訊同步。
2、每個Broker與Name Server叢集中的所有節點建立長連線,定時註冊Topic資訊到所有Name Server。
3、Producer與Name Server叢集中的其中一個節點(隨機選擇)建立長連線,定期從Name Server取Topic路由資訊。
4、Consumer與Name Server叢集中的其中一個節點(隨機選擇)建立長連線,定期從Name Server取Topic路由資訊。
這裡面最核心的是每個Broker與Name Server叢集中的所有節點建立長連線
這樣做好處多多。
1、這樣可以使Name Server之間可以沒有任何關聯,因為它們繫結的Broker是一致的。
2、作為Producer或者Consumer可以繫結任何一個Name Server 因為它們都是一樣的。
三、詳解Broker
1、Broker與Name Server關係
1)連線 單個Broker和所有Name Server保持長連線。
2)心跳
心跳間隔:每隔30秒向所有NameServer傳送心跳,心跳包含了自身的Topic配置資訊。
心跳超時:NameServer每隔10秒,掃描所有還存活的Broker連線,若某個連線2分鐘內沒有傳送心跳資料,則斷開連線。
3)斷開 :當Broker掛掉;NameServer會根據心跳超時主動關閉連線,一旦連線斷開,會更新Topic與佇列的對應關係,但不會通知生產者和消費者。
2、 負載均衡
一個Topic分佈在多個Broker上,一個Broker可以配置多個Topic,它們是多對多的關係。
如果某個Topic訊息量很大,應該給它多配置幾個Queue,並且儘量多分佈在不同Broker上,減輕某個Broker的壓力。
3 、可用性
由於訊息分佈在各個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恢復,未同步過去的訊息會被消費掉。
四 Consumer (消費者)
1 、Consumer與Name Server關係
1)連線 : 單個Consumer和一臺NameServer保持長連線,如果該NameServer掛掉,消費者會自動連線下一個NameServer,直到有可用連線為止,並能自動重連。
2)心跳: 與NameServer沒有心跳
3)輪詢時間 : 預設情況下,消費者每隔30秒從NameServer獲取所有Topic的最新佇列情況,這意味著某個Broker如果當機,客戶端最多要30秒才能感知。
2、 Consumer與Broker關係
1)連線 :單個消費者和該消費者關聯的所有broker保持長連線。
3、 負載均衡
叢集消費模式下,一個消費者叢集多臺機器共同消費一個Topic的多個佇列,一個佇列只會被一個消費者消費。如果某個消費者掛掉,分組內其它消費者會接替掛掉的消費者繼續消費。
五、 Producer(生產者)
1、 Producer與Name Server關係
1)連線 單個Producer和一臺NameServer保持長連線,如果該NameServer掛掉,生產者會自動連線下一個NameServer,直到有可用連線為止,並能自動重連。
2)輪詢時間 預設情況下,生產者每隔30秒從NameServer獲取所有Topic的最新佇列情況,這意味著某個Broker如果當機,生產者最多要30秒才能感知,在此期間,
發往該broker的訊息傳送失敗。
3)心跳 與nameserver沒有心跳
2、 與broker關係
連線 單個生產者和該生產者關聯的所有broker保持長連線。
參考
2、RocketMQ nameserver、broker之間的關係
只要自己變優秀了,其他的事情才會跟著好起來(中將8)