RocketMq之水平擴展及負載均衡

RocketMQ是一個分佈式具有高度可擴展性的消息中間件。本文旨在探索在broker端,生產端,以及消費端是如何做到橫向擴展以及負載均衡的。

Broker端水平擴展

Broker負載均衡

Broker是以group爲單位提供服務。一個group裏面分master和slave,master和slave存儲的數據一樣,slave從master同步數據(同步雙寫或異步複製看配置)。

通過nameserver暴露給客戶端後,只是客戶端關心(註冊或發送)一個個的topic路由信息。路由信息中會細化爲message queue的路由信息。而message queue會分佈在不同的broker group。所以對於客戶端來說,分佈在不同broker group的message queue爲成爲一個服務集羣,但客戶端會把請求分攤到不同的queue。

而由於壓力分攤到了不同的queue,不同的queue實際上分佈在不同的Broker group,也就是說壓力會分攤到不同的broker進程,這樣消息的存儲和轉發均起到了負載均衡的作用。

Broker一旦需要橫向擴展,只需要增加broker group,然後把對應的topic建上,客戶端的message queue集合即會變大,這樣對於broker的負載則由更多的broker group來進行分擔。

並且由於每個group下面的topic的配置都是獨立的,也就說可以讓group1下面的那個topic的queue數量是4,其他group下的topic queue數量是2,這樣group1則得到更大的負載。

commit log

雖然每個topic下面有很多message queue,但是message queue本身並不存儲消息。真正的消息存儲會寫在CommitLog的文件,message queue只是存儲CommitLog中對應的位置信息,方便通過message queue找到對應存儲在CommitLog的消息。

不同的topic,message queue都是寫到相同的CommitLog 文件,也就是說CommitLog完全的順序寫。

具體如下圖:

Producer

Producer端,每個實例在發消息的時候,默認會輪詢所有的message queue發送,以達到讓消息平均落在不同的queue上。而由於queue可以散落在不同的broker,所以消息就發送到不同的broker下,如下圖:

Consumer負載均衡

集羣模式

在集羣消費模式下,每條消息只需要投遞到訂閱這個topic的Consumer Group下的一個實例即可。RocketMQ採用主動拉取的方式拉取並消費消息,在拉取的時候需要明確指定拉取哪一條message queue。

而每當實例的數量有變更,都會觸發一次所有實例的負載均衡,這時候會按照queue的數量和實例的數量平均分配queue給每個實例。

默認的分配算法是AllocateMessageQueueAveragely,如下圖:


還有另外一種平均的算法是AllocateMessageQueueAveragelyByCircle,也是平均分攤每一條queue,只是以環狀輪流分queue的形式,如下圖:

需要注意的是,集羣模式下,queue都是隻允許分配只一個實例,這是由於如果多個實例同時消費一個queue的消息,由於拉取哪些消息是consumer主動控制的,那樣會導致同一個消息在不同的實例下被消費多次,所以算法上都是一個queue只分給一個consumer實例,一個consumer實例可以允許同時分到不同的queue。

通過增加consumer實例去分攤queue的消費,可以起到水平擴展的消費能力的作用。而有實例下線的時候,會重新觸發負載均衡,這時候原來分配到的queue將分配到其他實例上繼續消費。

但是如果consumer實例的數量比message queue的總數量還多的話,多出來的consumer實例將無法分到queue,也就無法消費到消息,也就無法起到分攤負載的作用了。所以需要控制讓queue的總數量大於等於consumer的數量。

廣播模式

由於廣播模式下要求一條消息需要投遞到一個消費組下面所有的消費者實例,所以也就沒有消息被分攤消費的說法。

在實現上,其中一個不同就是在consumer分配queue的時候,會所有consumer都分到所有的queue。

 

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