RocketMQ基本原理
Topic 基本原理
在Rocketmq集群中新建 Topic1
在管理界面中新建主題Topic1,為了方便觀察測試效果,這里把寫隊列和讀隊列的數量都設置成3。

這樣,在 broker-a 和 broker-b 上都創建了 Topic1 主題,並各創建了3寫3讀隊列,共6寫6讀,如下圖所示:

你也可以修改Topic1分別配置 broker-a 和 borker-b 上的隊列數量。
perm 參數的含義
perm 參數是設置隊列的讀寫權限,下面表格列出了可配置的值及其含義:
| 取值 | 含義 |
|---|---|
| 6 | 同時開啟讀寫 |
| 4 | 禁寫 |
| 2 | 禁讀 |
Topic 收發消息原理

生產者將消息發送到 Topic1 的其中一個寫隊列,消費者從對應的一個讀隊列接收消息。
生產者的負載均衡

生產者以輪詢的方式向所有寫隊列發送消息,這些隊列可能會分布在多個broker實例上。
消費者的負載均衡
一個 group 中的多個消費者,可以以負載均衡的方式來接收消息。
讀取隊列被均勻分配給這些消費者,它們從指定的隊列來接收消息。隊列的分配可以采用不同的策略,這里簡略介紹以下三種策略:
AllocateMessageQueueAveragely 平均分配
這是默認策略,它是這樣分配隊列的:

AllocateMessageQueueAveragelyByCircle 環形分配
如果使用環形分配,在消費者的代碼中需要設置分配策略,代碼如下:
consumer.setAllocateMessageQueueStrategy(new AllocateMessageQueueAveragelyByCircle());
這種分配策略的邏輯很簡單,所有0號隊列分給0號消費者,所有1號隊列分給1號消費者,以此類推。

AllocateMessageQueueConsistentHash 一致性哈希
如果使用一致性哈希算法進行分配,在消費者的代碼中需要設置分配策略,代碼如下:
consumer.setAllocateMessageQueueStrategy(new AllocateMessageQueueConsistentHash());
這種算法依靠一致性哈希算法,看當前消費者可以落到哪個虛擬節點,該虛擬節點對應哪個隊列。
問題
思考一下,如果寫隊列比讀隊列多會怎樣?反之會怎樣?
NameServer 基本原理

NameServer 是 rocketmq 自己開發的一個輕型注冊中心,他的作用相當於是 zk、eureka等。
rocketmq 為什么不使用 zk 呢?實際上 rocketmq 的早期版本使用的就是 zookeeper。
而 rocketmq 的架構設計決定了只需要一個輕量級的元數據服務器就足夠了。殺雞焉用牛刀?小區里,搞個貨架就行了,建個倉庫,又占地方,維護成本又高。
甚至,NameServer 都不需要有一個集群的管理者。以至於,NameServer 看起來都不像一個集群。事實上,NameServer 本質上來看,也不是一個集群。因為它的各個節點是獨立的,不相關的。每個 NameServer 都是獨立和 Producer、Consumer打交道。
基本認識
- NameServer主要用於存儲Topic,Broker關系信息,功能簡單,穩定性高。
- 各個NameServer節點之間不相關,不需要通信,單台宕機不影響其它節點。
- NameServer集群整體宕機不影響已建立關系的Concumer,Producer,Broker。
Broker、Producer、Consumer 與NameServer的通信
- 每個Borker和所有NameServer保持長連接,心跳間隔為30秒。每次心跳時還會攜帶當前的Topic信息。當某個Broker兩分鍾之內沒有心跳,則認為該Broker下線,並調整內存中與該Broker相關的Topic信息。
- Consumer 從 NameServer 獲得 Topic 的路由信息,與對應的 Broker 建立長連接。間隔30秒發送心跳至Broker。Broker檢查若發現某 Consumer 兩分鍾內無心跳則認為該Consumer下線,並通知該Consumer所有的消費者集群中的其他實例,觸發該消費者集群重新負載均衡。
- Producer 與消費者一樣,也是從 NameServer 獲得 Topic 的路由信息,與對應的 Broker 建立長連接,30秒發送一次心跳。Broker 也會認為兩分鍾內沒有心跳的 Producer 下線。
