RocketMQ -- 訊息拉取

大軍發表於2022-04-27

上一篇提到,由於訊息佇列負載機制,會往pullRequestQueue佇列放入一個個的PullRequest。

image.png

這些PullRequest會有一個專門的執行緒,把它取出來並封裝成服務端的一個Request,傳送給broker。

在傳送服務端之前,需要知道broker的地址在哪,需要從什麼偏移量開始拉取(偏移量叢集模式存broker,廣播模式存本地),一次性拉多少資料。

image.png

broker收到請求後,就會從commitlog中,根據偏移量把所需要的訊息給取出來,由於broker的主從同步,這邊返回訊息的時候,也會告知下一次拉取是從主broker拉取還是slave的broker拉取資料。

image.png

從commit拉取訊息的時候,會有這幾個情況(下面忽略offsetCheckInSlave判斷):

  1. 當前訊息佇列並沒有訊息,則下次拉取訊息的時候,如果這個broker是主節點,還是這個偏移量。如果這個broker是從節點,則下次直接從0開始。

image.png

  1. 當前訊息佇列有訊息,但是我們拉取的偏移量比佇列裡最小的偏移量還小,比如我們需要拉取100的資料,但是訊息佇列的最小偏移量是500。則下次拉取訊息的時候,如果這個broker是主節點,還是這個偏移量。如果這個broker是從節點,則下次直接從500開始。

image.png

  1. 如果我們我們拉取的偏移量剛好等於訊息佇列裡最大的偏移量,所以我們也沒有資料可以消費了,那下次拉取的時候,還是100這個偏移量。

image.png

  1. 如果我們我們拉取的偏移量大於訊息佇列裡最大的偏移量,所以我們也沒有資料可以消費了,那下次拉取的時候,這裡還要判斷訊息佇列裡最小的偏移量是否等於0。

image.png

  1. 正常情況下,我們需要的訊息是在訊息佇列裡最小的偏移量和最大的偏移量之間,那就直接把資料從commitlog中取出來並返回。

image.png

消費端接收broker響應後,就會根據上面各個情況的偏移量進行更新,並且把訊息存入PullRequest的processQueue中。

image.png

並且再把PullRequest放入pullRequestQueue佇列中,等待下次拉取。

processQueue的訊息如果來不及消費,會一直的堆積,所以PullRequest在拉取訊息的時候,會先判斷processQueue裡的訊息數量是否已經超過1000,如果超過了,則當前不拉取,並放入pullRequestQueue佇列中,50ms後才可以繼續拉取。

此外還會判斷processQueue中訊息的大小、processQueue中佇列最大偏移量與最小偏離量的間距,如果超過了閾值,也會放入pullRequestQueue佇列中,50ms後才可以繼續拉取。

相關文章