RocketMQ存儲篇——Config文件以及執行延遲消息的線程服務

在$HOME\store\config目錄下面存儲各類config文件,包括:consumerOffset.json、delayOffset.json、subscriptionGroup.json、topics.json四類config文件。
topics.json文件由TopicConfigManager類解析並存儲;存儲每個topic的讀寫隊列數、權限、是否順序等信息。
consumerOffset.json文件由ConsumerOffsetManager類解析並存儲;存儲每個消費者Consumer在每個topic上對於該topic的consumequeue隊列的消費進度;
delayOffset.json文件由ScheduleMessageService類解析並存儲;存儲對於延遲主題SCHEDULE_TOPIC_XXXX的每個consumequeue隊列的消費進度;
subscriptionGroup.json文件由SubscriptionGroupManager類解析並存儲;存儲每個消費者Consumer的訂閱信息。
各類圖機構如下:
這裏寫圖片描述

1 ScheduleMessageService執行延遲消息

該類除了解析並存儲delayOffset.json文件之外,還有一個重要的任務,就是定時執行延遲消息的任務。

在load方法中,將這些級別("1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h")的延時存入延遲級別delayLevelTable:ConcurrentHashMap<Integer /* level */, Long/* delay timeMillis */>變量中,例如1s的kv值爲1:1000,5s的kv值爲2:5000,key值依次類推;每個延遲級別即爲一個隊列。

在Broker啓動時調用ScheduleMessageService.start方法,在該方法處理兩件事:一、每個延遲隊列增加定時器;二、設置定時任務將延遲進度刷盤。
爲每個延遲級別設置一個定時器。遍歷delayLevelTable列表,key值爲level,並以level從offsetTable中獲取該級別的隊列消費進度offset。以level、offset爲參數初始化DeliverDelayedMessageTimerTask對象,並存入定時器中,在1秒之後在調用該對象的run方法。
延遲消費邏輯就在DeliverDelayedMessageTimerTask對象的run方法中。在該方法中調用executeOnTimeup方法,若該方法拋出異常,則重新初始化DeliverDelayedMessageTimerTask對象並放入定時器中,在10秒之後重新執行該對象。其中executeOnTimeup方法的業務邏輯如下:

1)調用DefaultMessageStore對象的findConsumeQueue(String topic, int queueId)方法獲取對應的ConsumeQueue對象;其中topic等於"SCHEDULE_TOPIC_XXXX";queueId等於延遲級別level減1;
2)以offset偏移量爲參數調用ConsumeQueue對象的getIndexBuffer方法獲取consumequeue的數據;若未獲取到ConsumeQueue對象則以offset、level爲參數初始化DeliverDelayedMessageTimerTask對象並放入定時器中,100毫秒之後再重新執行;
3)從consumequeue的數據中逐個繼續每個消息單元,根據每個消息單元的tagsCode檢查延遲時間是否已經到了,以tagsCode存儲的時間戳減去當前時間戳;
3.1)若大於零則表示延遲時間未到,則以該數據開始偏移量爲offset,對應的level爲參數初始化DeliverDelayedMessageTimerTask對象,並且在該時間差額之後再次調用該對象的run方法;然後更新ScheduleMessageService.offsetTable變量中相應延遲級別的offset值;
3.2)若小於等於零則表示延遲時間已經到了。首先以解析出來的物理偏移量commitLogOffset和消息大小size爲參數調用DefaultMessageStore對象的lookMessageByOffset(long commitLogOffset, int size)方法;然後將該方法返回的MessageExt對象轉換成MessageExtBrokerInner對象,其中,主要是將真實的topic和queueId從消息的properties中取出並設置到給MessageExtBrokerInner對象中;再調用DefaultMessageStore對象的putMessage(MessageExtBrokerInner msg)方法進行消息寫入。若寫入消息成功,則繼續解析後面的消息單元,然後重複執行第3步;否則以該數據開始偏移量爲offset、對應的level爲參數初始化DeliverDelayedMessageTimerTask對象並放入定時器中,在10秒之後重新執行;並且更新ScheduleMessageService.offsetTable變量中相應延遲級別的offset值;
4)在第3步中對獲取到的consumequeue數據逐個解析完成之後,將上述consumequeue數據的最後一個消息讀取偏移量之後的一個消息讀取偏移量(offset+consumequeue消息中的消息單元個數)作爲nextoffset、對應的level爲參數初始化DeliverDelayedMessageTimerTask對象並放入定時器中,100毫秒之後再重新執行;

2 收到發送消息時創建topic的配置信息(createTopicInSendMessageMethod)

調用TopicConfigManager.createTopicInSendMessageMethod(final String topic, final String defaultTopic,final String remoteAddress, final int clientDefaultTopicQueueNums, final int topicSysFlag)方法進行Topic配置的創建。大致邏輯如下:
1、以參數topic從TopicConfigManager.topicConfigTable中獲取該topic的配置信息對象TopicConfig;若獲取到了則直接返回該對象;否則創建一個新的配置對象並存入topicConfigTable變量中;
2、該topic不存在,則以參數defaultTopic從TopicConfigManager.topicConfigTable中獲取該topic的配置信息對象TopicConfig,該參數在Producer發送信息時默認爲"TBW102",而該topic在Broker啓動時會自動創建;
3、用topic來初始化新的TopicConfig對象,並用以defaultTopic獲取到的TopicConfig對象的其他參數來初始化新創建的TopicConfig對象;
4、將新創建的TopicConfig對象以topic爲key值存入TopicConfigManager.topicConfigTable變量中,並且更新dataVersion值;
5、然後將topicConfigTable變量值持久化到topics.json物理文件中。

3 根據GroupName查找訂閱組信息(findSubscriptionGroupConfig)

調用SubscriptionGroupManager.findSubscriptionGroupConfig(String GroupNmae)方法獲取訂閱信息。大致步驟如下:
1、以GroupNmae從SubscriptionGroupManager.SubscriptionGroupTable變量中獲取訂閱信息SubscriptionGroupConfig對象;若不爲空則直接返回該對象;
2、若爲空,表示還沒有該訂閱信息,再檢查Broker是否運行自動創建訂閱組(由配置參數autoCreateSubscriptionGroup設置,默認爲true)。若不允許則直接返回null;若允許則首先以GroupName爲參數創建SubscriptionGroupConfig對象,並存入SubscriptionGroupTable變量中;然後更新SubscriptionGroupManager的dataversion值;再將SubscriptionGroupManager的內容持久化到subscriptionGroup.json文件中;最後返回該新創建的SubscriptionGroupConfig對象;

4收到消費失敗時的回傳消息時創建topic的配置信息(createTopicInSendMessageBackMethod)

調用TopicConfigManager.createTopicInSendMessageBackMethod(String topic, int clientDefaultTopicQueueNums, int perm, int topicSysFlag)方法進行Topic配置的創建。大致邏輯如下:

1、以參數topic從TopicConfigManager.topicConfigTable中獲取該topic的配置信息對象TopicConfig;若獲取到了則直接返回該對象;否則創建一個新的配置對象並存入topicConfigTable變量中;
2、以該方法的入參初始化TopicConfig對象,並以topic爲key值存入TopicConfigManager.topicConfigTable變量中,並且更新dataVersion值;
3、然後將topicConfigTable變量值持久化到topics.json物理文件中。

發佈了59 篇原創文章 · 獲贊 56 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章