Broker
Broker充當着消息中轉角色,負責存儲消息、轉發消息。 Broker在 Rocketmq系統中負責接收並存儲從生產者發送來的消息,同時為消費者的拉取請求作准備。Broker同時也存儲着消息相關的元數據,包括消費者組消費進度偏移 offset、主題、隊列等。
-
Remoting Module:整個 Broker的實體,負責處理來自 clients端的請求。而這個Broker實體則由以下模塊構成:
-
Client Manager:客戶端管理器。負責接收、解析客戶端( Producer/Consumer)請求,管理客戶端。例如,維護 Consumer的Topic訂閱信息
-
Store service:存儲服務。提供方便簡單的AP接口,處理消息存儲到物理硬盤和消息査詢功能。
-
HA Service:高可用服務,提供 Master broker和 Slave broker之間的數據同步功能。
-
Index service:索引服務。根據特定的 Message key,對投遞到 Broker的消息進行索引服務,同時也提供根據 Message Key對消息進行快速查詢的功能。
為了增強 Broker性能與吞吐量, Broker一般都是以集群形式岀現的。各集群節點中可能存放着相同Topic的不同 Queue。不過,這里有個問題,如果某 Broker節點宕機,如何保證數據不丟失呢?其解決方案是,將每個Broker集群節點進行橫向擴展,即將 Broker節點再建為一個HA集群,解決單點問題。
Broker節點集群是一個主從集群,即集群中具有 Master與 Slave兩種角色。Master負責處理讀寫操作請求,而 Slave僅負責讀操作請求。一個 Maste可以包含多個 Slave,但一個 Slave只能隸屬於個 Master。Master與 Slave的對應關系是通過指定相同的 BrokerName、不同的 BrokerId來確定的。BrokerId為0表示Master,非0表示Slave,每個Broker與NameServer集群中的所有節點建立長連接,定時注冊Topic信息到所有 Nameserver。
工作流程
-
啟動 NameServer, NameServer啟動后開始監聽端口,等待 Broker、 Producer、 Consumer連接。
-
啟動 Broker時, Broker會與所有的 NameServer建立並保持長連接,然后每30秒向NameServer定時發送心跳包
-
發送消息前,可以先創建 Topic,創建 Topic時需要指定該 Topic要存儲在哪些 Broker上,當然,在創建Topic時也會將 Topic與 Broker的關系寫入到 NameServer中。不過,這步是可選的,也可以在發送消息時自動創建 Topic
-
Producer發送消息,啟動時先跟NameServer集群中的其中一台建立長連接,並從NameServer中獲取路由信息,即當前發送的 Topic消息的Queue與 Broker的地址(IP+port)的映射關系。然后根據算法策略從隊選擇一個 Queue,與隊列所在的 Broker建立長連接從而向 Broker發消息。當然,在獲取到路由信息后,Producer會首先將路由信息緩存到本地,再每30秒從 Name server更新一次路由信息。
-
Consumer跟 Producer類似,跟其中一台 Nameserver建立長連接,獲取其所訂閱 Topic的路由信息,然后根據算法策略從路由信息中獲取到其所要消費的queue,然后直接跟 Broker建立長連接,開始消費其中的消息。 Consumer在獲取到路由信息后,同樣也會每30秒從 Name Server更新一次路由信息。不過不同於Producer的是,Consumer還會向 Broker發送心跳,以確保 Broker的存活狀態。
手動Topic的創建有兩種模型
1.集群模式:該模式下創建的Topic在該集群中,所有Broker中的Queue數量是相同的
2.Broker模式:該模式下創建的Topic在該集群中,每個Broker中的Queue數量可以不同
自動創建Topic時,默認采用的是Broker模式,會為每個Broker默認創建4個Queue
讀寫隊列
從物理上來講,讀寫隊列是同一個隊列。所以,不存在讀寫隊列數據同步問題。讀寫隊列是邏輯上進行區分的概念。一般情況下,讀寫隊列數量是一樣的。
例如,創建Topic時設置的寫隊列數量為8,讀隊列數量為4,此時系統會創建8個 Queue,分別是0 1 2 3 4 5 6 7。Producer會將消息寫入到這8個隊列,但 Consumer只會消費0 1 2 3這4個隊列中的消息,4 5 6 7中的消息是不會被消費到的。
再如,創建 Topick時設置的寫隊列數量為4,讀隊列數量為8,此時系統會創建8個 Queue,分別是0 1 2 3 4 5 6 7。Producer會將消息寫入到0 1 2 3這4個隊列,但 Consumer只會消費0 1 2 3 4 5 6 7這8個隊列中的消息,但是4567中是沒有消息的。此時假設Consumer Group中包含兩個Consumer,Consumer1消費0 1 2 3,而Consumer2消費4 5 6 7。但實際情況,Consumer2是沒有消息可以消費。
也就是當讀寫隊列數量不一致時,總是有問題的。其這樣設計的目的是為了方便Topic的Queue的縮容。
例如,原來創建的Topic中包含16個Queue,如何能夠使其Queue縮容為8個,還不會丟失消息?可以動態修改寫隊列數量為8,讀隊列數量不變。此時新的消息只能寫入到前8個隊列,而消費都消費的卻是16個隊列中的數據。當發現后8個 Queue中的消息消費完畢后,就可以再將讀隊列數量動態設置為8.
perm
perm用於設置對當前創建Topic的操作權限:2表示只寫,4表示只讀,6表示讀寫