RocketMQ核心概念掃盲篇

點擊上方“中間件興趣圈”選擇“設爲星標”

做積極的人,越努力越幸運!

在正式進入RocketMQ的學習之前,我覺得有必要梳理一下RocketMQ核心概念,爲大家學習RocketMQ打下牢固的基礎。

1、RocketMQ部署架構


在RocketMQ主要的組件如下:
  • Nameserver

    Nameserver集羣,topic的路由註冊中心,爲客戶端根據Topic提供路由服務,從而引導客戶端向Broker發送消息。Nameserver之間的節點不通信。路由信息在Nameserver集羣中數據一致性採取的最終一致性。

  • Broker

    消息存儲服務器,分爲兩種角色:Master與Slave,上圖中呈現的就是2主2從的部署架構,在RocketMQ中,主服務承擔讀寫操作,從服務器作爲一個備份,當主服務器存在壓力時,從服務器可以承擔讀服務(消息消費)。所有Broker,包含Slave服務器每隔30s會向Nameserver發送心跳包,心跳包中會包含存在在Broker上所有的topic的路由信息。

  • Client

    消息客戶端,包括Producer(消息發送者)和Consumer(消費消費者).客戶端在同一時間只會連接一臺nameserver,只有在連接出現異常時纔會嘗試連接另外一臺。客戶端每隔30s向Nameserver發起topic的路由信息查詢。

溫馨提示:Nameserver是在內存中存儲Topic的路由信息,持久化Topic路由信息的地方是在Broker中,即${    ROCKETMQ_HOME}/store/config/topics.json。

在RocketMQ4.5.0版本後引入了多副本機制,即一個複製組(m-s)可以演變爲基於raft協議的複製組,複製組內部使用raft協議保證broker節點數據的強一致性,該部署架構在金融行業用的比較多。

2、消息訂閱模型


在RocketMQ的消息消費模式採用的是發佈與訂閱模式。

topic:一類消息的集合,消息發送者將一類消息發送到一個主題中,例如訂單模塊將訂單發送到 order_topic 中,而用戶登錄時,將登錄事件發送到 user_login_topic 中。

consumegroup:消息消費組,一個消費單位的“羣體”,消費組首先在啓動時需要訂閱需要消費的topic。一個topic可以被多個消費組訂閱,同樣一個消費組也可以訂閱多個主題。一個消費組擁有多個消費者。

術語解釋起來有點枯燥晦澀,接下來我舉例來闡述。

例如我們在開發一個訂單系統,其中有一個子系統:order-service-app,在該項目中會創建一個消費組order_consumer來訂閱 order_topic,並且基於分佈式部署,order-service-app的部署情況如下:

即order-service-app部署了3臺服務器,每一個jvm進程可以看做是消費組 order_consumer 消費組的其中一個消費者。

2.1 消費模式

那這三個消費者如何來分工來共同消費 order_topic 中的消息呢?

在RocketMQ中支持廣播模式與集羣模式。

廣播模式:一個消費組內的所有消費者每一個都會處理topic中的每一條消息,通常用於刷新內存緩存。

集羣模式:一個消費組內的所有消費者共同消費一個topic中的消息,即分工協作,一個消費者消費一部分數據,啓動負載均衡,

集羣模式是非常普遍的模式,符合分佈式架構的基本理念,即橫向擴容,當前消費者如果無法快速及時處理消息時,可以通過增加消費者的個數橫向擴容,快速提高消費能力,及時處理擠壓的消息。

2.2 消費隊列負載算法與重平衡機制

那集羣模式下,消費者是如何來分配消息的呢?

例如上面實例中order_topic有16個隊列,那一個擁有3個消費者的消費組如何來分配隊列中。

在MQ領域有一個不成文的約定:同一個消費者同一時間可以分配多個隊列,但一個隊列同一時間只會分配給一個消費者。

RocketMQ提供了衆多的隊列負載算法,其中最常用的兩種平均分配算法。

  • AllocateMessageQueueAveragely

    平均分配

  • AllocateMessageQueueAveragelyByCircle

    輪流平均分配

爲了說明這兩種分配算法的分配規則,現在對16個隊列,進行編號,用q0~q15表示,消費者用c0~c2表示。

AllocateMessageQueueAveragely分配算法的隊列負載機制如下:

c0:q0 q1 q2 q3 q4 q5

c1:   q6 q7 q8 q9 q10

c2:    q11 q12 q13 q14 q15

其算法的特點是用總數除以消費者個數,餘數按消費者順序分配給消費者,故c0會多分配一個隊列,而且隊列分配是連續的。

AllocateMessageQueueAveragelyByCircle分配算法的隊列負載機制如下:

c0:q0  q3 q6 q9 q12 q15

c1:   q1   q4 q7 q10 q13

c2:    q2   q5 q8 q11 q14

該分配算法的特點就是輪流一個一個分配。

溫馨提示:如果topic的隊列個數小於消費者的個數,那有些消費者無法分配到消息。在RocketMQ中一個topic的隊列數直接決定了最大消費者的個數,但topic隊列個數的增加對RocketMQ的性能不會產生影響。

在實際過程中,對主題進行擴容(增加隊列個數)或者對消費者進行擴容、縮容是一件非常尋常的事情,那如果新增一個消費者,該消費者消費哪些隊列呢?這就涉及到消息消費隊列的重新分配,即消費隊列重平衡機制

在RocketMQ客戶端中會每隔20s去查詢當前topic的所有隊列、消費者的個數,運用隊列負載算法進行重新分配,然後與上一次的分配結果進行對比,如果發生了變化,則進行隊列重新分配;如果沒有發生變化,則忽略。

例如採取的分配算法如下圖所示,現在增加一個消費者c3,那隊列的分佈情況是怎樣的呢?

根據新的分配算法,其隊列最終的情況如下:

c0:q0 q1 q2 q3

c1:   q4 q5 q6 q7

c2:    q8 q9 q10 q11

c3:    q12 q13 q14  q15

上述整個過程無需應用程序干預,由RocketMQ完成。大概的做法就是將將原先分配給自己但這次不屬於的隊列進行丟棄,新分配的隊列則創建新的拉取任務。

2.3 消費進度

消費者消費一條消息後需要記錄消費的位置,這樣在消費端重啓的時候,繼續從上一次消費的位點開始進行處理新的消息。在RocketMQ中,消息消費位點的存儲是以消費組爲單位的。

集羣模式下,消息消費進度存儲在broker端,

不能識別此Latex公式:
 { ROCKETMQ_HOME }/store/config/consumerOffset.json 是其具體的存儲文件,其中內容截圖如下:

可見消費進度的Key爲:topic@consumeGroup,然後每一個隊列一個偏移量。



廣播模式的消費進度文件存儲在用戶的主目錄,默認文件全路勁名:

{ USER_HOME }/.rocketmq_offsets。

2.4 消費模型

RocketMQ提供了併發消費、順序消費兩種消費模型。

併發消費:對一個隊列中消息,每一個消費者內部都會創建一個線程池,對隊列中的消息多線程處理,即偏移量大的消息比偏移量小的消息有可能先消費。

順序消費:在某一項場景,例如MySQL binlog 場景,需要消息按順序進行消費。在RocketMQ中提供了基於隊列的順序消費模型,即儘管一個消費組中的消費者會創建一個多線程,但針對同一個Queue,會加鎖。

溫馨提示:併發消費模型中,消息消費失敗默認會重試16次,每一次的間隔時間不一樣;而順序消費,如果一條消息消費失敗,則會一直消費,直到消費成功。故在順序消費的使用過程中,應用程序需要區分系統異常、業務異常,如果是不符合業務規則導致的異常,則重試多少次都無法消費成功,這個時候一定要告警機制,及時進行人爲干預,否則消費會積壓。

3、事務消息


事務消息並不是爲了解決分佈式事務,而是提供消息發送與業務落庫的一致性,其實現原理就是一次分佈式事務的具體運用,請看如下示例:

上述僞代碼中,將訂單存儲關係型數據庫中和將消息發送到MQ這是兩個不同介質的兩個操作,如果能保證消息發送、數據庫存儲這兩個操作要麼同時成功,要麼同時失敗,RocketMQ爲了解決該問題引入了 事務消息

溫馨提示,本節主要的目的是讓大家知曉各個術語的概念,由於事務消息的使用,將在該專欄的後續文章中詳細介紹。

4、定時消息


開源版本的RocketMQ目前並不支持任意精度的定時消息。所謂的定時消息就是將消息發送到Broker,但消費端不會立即消費,而是要到指定延遲時間後才能被消費端消費。

RocketMQ目前支持指定級別的延遲,其延遲級別如下:

1s 5s 10s 30s 12345678910203012h

5、消息過濾


消息過濾是指消費端可以根據某些條件對一個topic中的消息進行過濾,即只消費一個主題下滿足過濾條件的消息。

RocketMQ目前主要的過濾機制是基於tag的過濾與基於消息屬性的過濾,基於消息屬性的過濾支持SQL92表達式,對消息進行過濾。

6、小結


本文的主要目的是介紹RocketMQ常見的術語,例如nameserver、broker、主題、消費組、消費者、隊列負載算法、隊列重平衡機制、併發消費、順序消費、消費進度存儲、定時消息、事務消息、消息過濾等基本概念,爲後續的實戰系列打下堅實基礎。


本文來自筆者的另一力作《RocketMQ實戰與進階》,專欄從使用場景入手介紹如何使用 RocketMQ,使用過程中遇到什麼問題,如何解決這些問題,以及爲什麼可以這樣解決,即原理講解(圖)穿插在實戰中。專欄的設計思路重在強調實戰二字,旨在讓一位 RocketMQ 初學者通過對本專欄的學習,快速“打怪升級”,理論與實戰結合,成爲該領域的佼佼者。


本文分享自微信公衆號 - 中間件興趣圈(dingwpmz_zjj)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章