RocketMQ基本概念介紹

初步接觸了RocketMQ后發(fā)現其與傳統意義上的實現JMS協議的消息隊列(如ActiveMQ)存在著不小的區(qū)別,很有必要對其中的一些概念做個說明。



NameServer集群

NameServer的作用是注冊中心,類似于Zookeeper,但又有區(qū)別于它的地方。每個NameServer節(jié)點互相之間是獨立的,沒有任何信息交互,也就不存在任何的選主或者主從切換之類的問題,因此NameServer與Zookeeper相比更輕量級。單個NameServer節(jié)點中存儲了活躍的Broker列表(包括master和slave),這里活躍的定義是與NameServer保持有心跳。

Broker集群

Broker是具體提供業(yè)務的服務器,單個Broker節(jié)點與所有的NameServer節(jié)點保持長連接及心跳,并會定時將Topic信息注冊到NameServer,順帶一提底層的通信和連接都是基于Netty實現的。

Broker中分master和slave兩種角色,每個master可以對應多個slave,但一個slave只能對應一個master,master和slave通過指定相同的Brokername,不同的BrokerId (master為0)成為一個組。master和slave之間的同步方式分為同步雙寫和異步復制,異步復制方式master和slave之間雖然會存在少量的延遲,但性能較同步雙寫方式要高出10%左右。

另外,Broker中還存在一些非常重要的名詞需要說明:

Topic和Queue

RocketMQ的Topic/Queue和JMS中的Topic/Queue概念有一定的差異,JMS中所有消費者都會消費一個Topic消息的副本,而Queue中消息只會被一個消費者消費;但到了RocketMQ中Topic只代表普通的消息隊列,而Queue是組成Topic的更小單元,集群消費模式下一個消費者只消費該Topic中部分Queue中的消息,當一個消費者開啟廣播模式時則會消費該Topic下所有Queue中的消息




Tags

Tags是Topic下的次級消息類型(注:Tags也支持TagA || TagB這樣的表達式),可以在同一個Topic下基于Tags進行消息過濾。Tags的過濾需要經過兩次比對,首先會在Broker端通過Tag hashcode進行一次比對過濾,匹配成功傳到consumer端后再對具體Tags進行比對,以防止Tag hashcode重復的情況。Queue中具體的存儲單元結構如下圖:

Queue單個存儲單元結構.png

Producer集群

與nameserver的關系

單個Producer和一臺nameserver保持長連接,定時查詢topic配置信息,如果該nameserver掛掉,生產者會自動連接下一個nameserver,直到有可用連接為止,并能自動重連。與nameserver之間沒有心跳。

與broker的關系

單個Producer和與其關聯的所有broker保持長連接,并維持心跳。默認情況下消息發(fā)送采用輪詢方式,會均勻發(fā)到對應Topic的所有queue中。

最佳實踐

一個應用盡可能只使用一個 Topic,消息子類型用 tags 來標識,tags 可以由應用自由設置。只有發(fā)送消息設置了tags,消費方在訂閱消息時,才可以利用 tags 在 broker 做消息過濾。

每個消息在業(yè)務層面的唯一標識碼,要設置到 keys 字段,方便將來定位消息丟失問題。服務器會為每個消

息創(chuàng)建索引(哈希索引),應用可以通過 Topic,key 來查詢返條消息內容,以及消息被誰消費。由于是哈希索引,請務必保證 key 盡可能唯一,這樣可以避免潛在的哈希沖突。

消息發(fā)送成功或者失敗,要打印消息日志,務必要打印 sendresult 和 key 字段。

對于消息不可丟失應用,務必要有消息重發(fā)機制。例如:消息發(fā)送失敗,存儲到數據庫,能有定時程序嘗試重發(fā)或者人工觸發(fā)重發(fā)。

某些應用如果不關注消息是否發(fā)送成功,請直接使用sendOneWay方法發(fā)送消息。

Consumer集群

與nameserver的關系

單個Consumer和一臺nameserver保持長連接,定時查詢topic配置信息,如果該nameserver掛掉,消費者會自動連接下一個nameserver,直到有可用連接為止,并能自動重連。與nameserver之間沒有心跳。

與broker的關系

單個Consumer和與其關聯的所有broker保持長連接,并維持心跳,失去心跳后,則關閉連接,并向該消費者分組的所有消費者發(fā)出通知,分組內消費者重新分配隊列繼續(xù)消費。

最佳實踐

Consumer 數量要小于等于queue的總數量,由于Topic下的queue會被相對均勻的分配給Consumer,如果 Consumer 超過queue的數量,那多余的 Consumer 將沒有queue可以消費消息。

消費過程要做到冪等(即消費端去重),RocketMQ為了保證性能并不支持嚴格的消息去重。

盡量使用批量方式消費,RocketMQ消費端采用pull方式拉取消息,通過consumeMessageBatchMaxSize參數可以增加單次拉取的消息數量,可以很大程度上提高消費吞吐量。另外,提高消費并行度也可以通過增加Consumer處理線程的方式,對應參數consumeThreadMin和consumeThreadMax。

消息發(fā)送成功或者失敗,要打印消息日志。

補充

線上建議關閉autoCreateTopicEnable配置

該配置用于在Topic不存在時自動創(chuàng)建,會造成的問題是自動新建的Topic只會存在于一臺broker上,后續(xù)所有對該Topic的請求都會局限在單臺broker上,造成單點壓力。

broker master宕機情況是否會丟消息

broker master宕機,雖然理論上來說不能向該broker寫入但slave仍然能支持消費,但受限于rocketmq的網絡連接機制,默認情況下最多需要30秒,消費者才會發(fā)現該情況,這個時間可通過修改參數pollNameServerInteval來縮短。這個時間段內,發(fā)往該broker的請求都是失敗的,而且該broker的消息無法消費,因為此時消費者不知道該broker已經掛掉。 直到消費者得到master宕機通知后,才會轉向slave進行消費,但是slave不能保證master的消息100%都同步過來了,因此會有少量的消息丟失。但是消息最終不會丟,一旦master恢復,未同步過去的消息仍然會被消費掉。

?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容