天天看點

rocketMq原理_nameserver與broker的互動

本文從namesrv與broker的互動角度,講述namesrv的具體作用,以及與broker的關系:

broker啟動時,需要指定namesrv位址(一個或多個),在建立好與所有namesrv的連接配接後,broker的一個重要任務就是向這些namesrv注冊路由資訊:

         namesrv在記憶體中維護了下面幾個資料結構,用于儲存broker注冊的有關資料,這些資料統稱為路由資訊,路由資訊一個最重要的作用就是告訴consumer和producer,生産者可以往哪裡發送消息,消費者可以從哪裡進行拉取到消息,(後面一篇文章rocketMq工作原理_用戶端與namesrv及broker的互動中有介紹到生産者與消費者如何進行路由資料拉取以及如何使用該資料進行消息生産和消費)

       HashMap<String, List<QueueData>> topicQueueTable;

       HashMap<String, BrokerData> brokerAddrTable;

       HashMap<String, Set<String>> clusterAddrTable;

       HashMap<String, BrokerLiveInfo> brokerLiveTable;

       HashMap<String, List<String>> filterServerTable;

brokerAddrTable:維護了所有broker(包括master和slave)的位址資訊,brokerData結構如下:

rocketMq原理_nameserver與broker的互動

        cluster表示目前broker所屬的broker叢集名稱

topicQueueTable:維護了所有topic對應的隊列資訊,如topicA在broker1上對應了幾個可讀可寫queue,在broker2上對應了幾個queue,queueData結構如下:(每個topic為何對應多個queue下面有介紹)

rocketMq原理_nameserver與broker的互動

brokerLiveTable:維護了所有master-broker的心跳資訊:

rocketMq原理_nameserver與broker的互動

       其中dataVersion在broker端維護,每當broker端有配置發生變更,該值會遞增,當namesrv發現該值變動時,則會對應更新記憶體中的資料;

       haServerAddr表示該master broker打開的用于主從通信的IP:port資訊,在接受broker發來的注冊請求時,如果發現是slave broker,則會找到其對應主master的haServerAddr資訊,并傳回給slave broker,slave broker根據該位址與master建立連接配接,之後的消息同步以及其他資料的同步就在此連接配接上進行。

namesrv對于broker下線的處理:

       1).如果broker當機,會調起netty的channel關閉事件,namesrv會進行路由資訊清理等操作。namesrv端添加了netty的IdleStateHandler進行會話管理,如果與broker的連接配接超過120秒(預設)未發生讀寫事件,則執行會話清理以及路由清理工作。

       2)另外,如果與broker端的網絡不暢,namesrv端如果發現(10秒一次定時任務進行路由資訊掃描)某個broker的路由資訊超過120秒未更新,則也會進行路由清理

       NameServer在清除失活Broker之後,并不會主動通知用戶端,用戶端每隔30秒會請求NameServer并擷取最新的路由表,那麼就意味着,如果隻依賴nameServer的主動通知,用戶端總會有30秒的延時,無法實時感覺Broker伺服器的當機。是以在這個30秒裡,生産者依舊會向故障的Broker發送消息,消費者也同樣會試圖從故障的上拉取消息,那麼消息發送和消費的高可用性如何保證呢?

       在生産者進行消息發送時,預設選擇failover機制(失敗切換)來保證消息發送的高可用。當消息生産者向Broker發送消息傳回異常後,會選擇另外一個Broker上的消息隊列進行重試,結合重試機制,實作消息發送的高可用。不同于生産者,消費者發現拉取消息失敗後,會選擇切換到故障broker的slave broker上進行消息拉取,試下消息拉取的高可用

同時由于不需要NameServer通知衆多不固定的生産者,也降低了NameServer實作的複雜性。

namesrv當機:

       namesrv叢集目的是為了高可用,前面說到broker向所有namesrv注冊路由資訊,是以即使其中一台挂掉,也不影響整體使用。當用戶端發現自己連接配接的namesrv挂掉後,會切換到另一台namesrv上擷取路由資訊,由于多個namesrv之間不會互相通信,是以namesrv上的路由資訊并不保證強一緻,屬于AP架構(分區容錯+可用性)

重點來啦:broker中的queue是什麼意思,每個topic對應多個queue用意是什麼?

要解釋這個問題,首先得簡單說說broker中消息的存儲機制:

       broker中,消息内容被存儲在commitLog檔案中,broker通過commitLog檔案順序寫進行消息存儲,此外,broker還為每個topic維護了n個queue(對應n個consumequeue檔案),如圖

rocketMq原理_nameserver與broker的互動

,topic_1對應了四個consumequeue檔案夾,每個檔案夾中都有一個或多個consumequeue檔案,每次向commitLog中寫入一條消息後,還會向對應queueId的queue中寫入一條資料,queue中存儲的是commitLog中寫入消息的具體位置、消息生産時的tag、消息大小等資訊(下面就稱為位置資訊),在消息拉取時,會從queue中先拿到消息的位置資訊,再從commitLog中查詢。

在消息生産負載均衡,消息消費能力橫向擴充,broker橫向擴充方面,queue的意義是及其關鍵的,在下文rocketMq工作原理_用戶端與namesrv及broker的互動中會有詳細介紹,無論你是僅僅想知道為啥rocketMq擴充能力這麼優秀,還是想要深入了解rocketMq,都必須對queue有更清楚的認知

順帶提下broker中消息删除機制:和傳統mq(如activityMq),不一樣,rocketmq中的消息不會在消費完成後進行删除,而是定期進行清理,這樣有以下幾個好處:

  1. rocketMq中一個消息往往被N個消費組消費,但消息隻需要存儲一份,消費進度單獨記錄互不影響,同一個消息,不同的消費者組的對其消費是互不影響的。下面一篇文章裡會有詳細介紹
  2. 由于消費從哪裡消費的決定權一直都是用戶端決定,是以隻要消息還在,就可以消費到,這使得RocketMQ可以支援其他傳統消息中間件不支援的回溯消費

繼續閱讀