Java的RocketMq水平擴展及負載均衡詳解
前言
RocketMQ是一個分布式具有高度可擴展性的消息中間件。
本文旨在探索在broker端,生產端,以及消費端是如何做到橫向擴展以及負載均衡的。
Broker端水平擴展
Broker負載均衡
Broker是以group為單位提供服務。一個group里面分master和slave,master和slave存儲的數(shù)據(jù)一樣,slave從master同步數(shù)據(jù)(同步雙寫或異步復制看配置)。
通過nameserver暴露給客戶端后,只是客戶端關心(注冊或發(fā)送)一個個的topic路由信息。路由信息中會細化為message queue的路由信息。而message queue會分布在不同的broker group。所以對于客戶端來說,分布在不同broker group的message queue為成為一個服務集群,但客戶端會把請求分攤到不同的queue。
而由于壓力分攤到了不同的queue,不同的queue實際上分布在不同的Broker group,也就是說壓力會分攤到不同的broker進程,這樣消息的存儲和轉發(fā)均起到了負載均衡的作用。
Broker一旦需要橫向擴展,只需要增加broker group,然后把對應的topic建上,客戶端的message queue集合即會變大,這樣對于broker的負載則由更多的broker group來進行分擔。
并且由于每個group下面的topic的配置都是獨立的,也就說可以讓group1下面的那個topic的queue數(shù)量是4,其他group下的topic queue數(shù)量是2,這樣group1則得到更大的負載。
commit log
雖然每個topic下面有很多message queue,但是message queue本身并不存儲消息。真正的消息存儲會寫在CommitLog的文件,message queue只是存儲CommitLog中對應的位置信息,方便通過message queue找到對應存儲在CommitLog的消息。
不同的topic,message queue都是寫到相同的CommitLog 文件,也就是說CommitLog完全的順序寫。
具體如下圖:

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

Consumer負載均衡
集群模式
在集群消費模式下,每條消息只需要投遞到訂閱這個topic的Consumer Group下的一個實例即可。RocketMQ采用主動拉取的方式拉取并消費消息,在拉取的時候需要明確指定拉取哪一條message queue。
而每當實例的數(shù)量有變更,都會觸發(fā)一次所有實例的負載均衡,這時候會按照queue的數(shù)量和實例的數(shù)量平均分配queue給每個實例。
默認的分配算法是AllocateMessageQueueAveragely,如下圖:

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

需要注意的是,集群模式下,queue都是只允許分配只一個實例,這是由于如果多個實例同時消費一個queue的消息,由于拉取哪些消息是consumer主動控制的,那樣會導致同一個消息在不同的實例下被消費多次,所以算法上都是一個queue只分給一個consumer實例,一個consumer實例可以允許同時分到不同的queue。
通過增加consumer實例去分攤queue的消費,可以起到水平擴展的消費能力的作用。而有實例下線的時候,會重新觸發(fā)負載均衡,這時候原來分配到的queue將分配到其他實例上繼續(xù)消費。
但是如果consumer實例的數(shù)量比message queue的總數(shù)量還多的話,多出來的consumer實例將無法分到queue,也就無法消費到消息,也就無法起到分攤負載的作用了。所以需要控制讓queue的總數(shù)量大于等于consumer的數(shù)量。
廣播模式
由于廣播模式下要求一條消息需要投遞到一個消費組下面所有的消費者實例,所以也就沒有消息被分攤消費的說法。
在實現(xiàn)上,其中一個不同就是在consumer分配queue的時候,會所有consumer都分到所有的queue。

到此這篇關于Java的RocketMq水平擴展及負載均衡詳解的文章就介紹到這了,更多相關RocketMq水平擴展及負載均衡內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java中Integer的parseInt和valueOf的區(qū)別詳解
這篇文章主要介紹了Java中Integer的parseInt和valueOf的區(qū)別詳解,nteger.parseInt(s)是把字符串解析成int基本類型,Integer.valueOf(s)是把字符串解析成Integer對象類型,其實int就是Integer解包裝,Integer就是int的包裝,需要的朋友可以參考下2023-11-11
SpringBoot實現(xiàn)JWT令牌失效的6種方案
JWT(JSON?Web?Token)作為一種輕量級的認證方式,被廣泛應用于現(xiàn)代Web應用和微服務架構中,然而,JWT的無狀態(tài)特性雖然帶來了擴展性優(yōu)勢,卻也帶來了令牌管理的挑戰(zhàn),特別是當需要使令牌提前失效時,本文將介紹在SpringBoot應用中實現(xiàn)JWT令牌失效的6種方案2025-06-06

