一個Topic是一個主題。一個系統中,我們可以将消息劃成Topic,這樣,将不同的消息發送到不同的queue。
Queue一個topic下,我們可以設定多個queue,每個queue就是我們平時所說的消息隊列;因為queue是完全從屬于某個特定的topic的,是以當我們要發送消息時,總是要指定該消息所屬的topic是什麼。然後equeue就能知道該topic下有幾個queue了。但是到底發送到哪個queue呢?比如一個topic下有4個queue,那對于這個topic下的消息,發送時,到底該發送到哪個queue呢?那必定有個消息被路由的過程。目前equeue的做法是在發送一個消息時,需要使用者指定這個消息對應的topic以及一個用來路由的一個object類型的參數。equeue會根據topic得到所有的queue,然後根據該object參數通過hash code然後取模queue的個數最後得到要發送的queue的編号,進而知道該發送到哪個queue。這個路由消息的過程是在發送消息的這一方做的,也就是下面要說的producer。之是以不在消息伺服器上做是因為這樣可以讓使用者自己決定該如何路由消息,具有更大的靈活性。
注意topic與queue的關系如下圖所示:

就是消息隊列的生産者。我們知道,消息隊列的本質就是實作了publish-subscribe的模式,即生産者-消費者模式。生産者生産消息,消費者消費消息。是以這裡的Producer就是用來生産和發送消息的。
Consumer就是消息隊列的消費者,一個消息可以有多個消費者。
Consumer Group消費者分組,這可能對大家來說是一個新概念。之是以要搞出一個消費者分組,是為了實作下面要說的叢集消費。
一個消費者分組中包含了一些消費者,如果這些消費者是要叢集消費,那這些消費者會平均消費該分組中的消息。 Brokerequeue中的broker負責消息的中轉,即接收producer發送過來的消息,然後持久化消息到磁盤,然後接收consumer發送過來的拉取消息的請求,然後根據請求拉取相應的消息給consumer。是以,broker可以了解為消息隊列伺服器,提供消息的接收、存儲、拉取服務。可見,broker對于equeue來說是核心,它絕對不能挂,一旦挂了,那producer,consumer就無法實作publish-subscribe了。
叢集消費叢集消費是指,
一個consumer group下的consumer,平均消費topic下的queue。具體如何平均可以看一下下面的架構圖,這裡先用文字簡單描述一下。假如一個topic下有4個queue,然後目前有一個consumer group,該分組下有4個consumer,那每個consumer就被配置設定到該topic下的一個queue,這樣就達到了平均消費topic下的queue的目的。如果consumer group下隻有兩個consumer,那每個consumer就消費2個queue。如果有3個consumer,則第一個消費2個queue,後面兩個每個消費一個queue,進而達到盡量平均消費。是以,可以看出,我們應該
盡量讓consumer group下的consumer的數目和topic的queue的數目一緻或成倍數關系。這樣每個consumer消費的queue的數量總是一樣的,這樣每個consumer伺服器的
壓力才會差不多。目前前提是這個topic下的每個queue裡的消息的數量總是差不多多的。這點我們可以對消息根據某個使用者自己定義的key來進行hash路由來保證。
廣播消費廣播消費是指一個consumer隻要訂閱了某個topic的消息,那它就會收到該topic下的所有queue裡的消息,而不管這個consumer的group是什麼。是以
對于廣播消費來說,consumer group沒什麼實際意義。consumer可以在執行個體化時,我們可以指定是叢集消費還是廣播消費。
消費進度 (offset)消費進度是指,當一個consumer group裡的consumer在消費某個queue裡的消息時,equeue是通過記錄消費位置(offset)來知道目前消費到哪裡了。以便該consumer重新開機後繼續從該位置開始消費。比如一個topic有4個queue,一個consumer group有4個consumer,則每個consumer配置設定到一個queue,然後每個consumer分别消費自己的queue裡的消息。equeue會分别記錄每個consumer對其queue的消費進度,進而保證每個consumer重新開機後知道下次從哪裡開始繼續消費。實際上,也許下次重新開機後不是由該consumer消費該queue了,而是由group裡的其他consumer消費了,這樣也沒關系,因為我們已經記錄了這個queue的消費位置了。是以可以看出,消費位置和consumer其實無關,消費位置完全是queue的一個屬性,用來記錄目前被消費到哪裡了。另外一點很重要的是,
一個 topic 可以被多個 consumer group 裡 的 consumer 訂閱。不同consumer group裡的consumer即便是消費同一個topic下的同一個queue,那消費進度也是分開存儲的。也就是說,不同的consumer group内的consumer的消費完全隔離,彼此不受影響。還有一點就是,對于叢集消費和廣播消費,消費進度持久化的地方是不同的,叢集消費的消費進度是放在broker,也就是消息隊列伺服器上的,而廣播消費的消費進度是存儲在consumer本地磁盤上的。之是以這樣設計是因為,對于叢集消費,由于一個queue的消費者可能會更換,因為consumer group下的consumer數量可能會增加或減少,然後就會重新計算每個consumer該消費的queue是哪些,這個能了解的把?是以,當出現一個queue的consumer變動的時候,新的consumer如何知道該從哪裡開始消費這個queue呢?如果這個queue的消費進度是存儲在前一個consumer伺服器上的,那就很難拿到這個消費進度了,因為有可能那個伺服器已經挂了,或者下架了,都有可能。而因為broker對于所有的consumer總是在服務的,是以,在叢集消費的情況下,被訂閱的topic的queue的消費位置是存儲在broker上的,存儲的時候按照不同的consumer group做隔離,以確定不同的consumer group下的consumer的消費進度互補影響。然後,對于廣播消費,由于不會出現一個queue的consumer會變動的情況,是以我們沒必要讓broker來儲存消費位置,是以是儲存在consumer自己的伺服器上。
broker配置檔案說明
lstorePathRootDir,資料存放的根目錄
lstorePathCommitLog,commitlog存放的路徑
lmapedFileSizeCommitLog= 1024 * 1024 * 1024,每個commitlog大小,
預設為1G lmapedFileSizeConsumeQueue= 300000 * 20,消費隊列檔案大小,
預設為存儲30W條消息,每條消息20個位元組,詳細參考
ConsumeQueue lflushIntervalCommitLog= 1000,commit log刷盤間隔,
預設1秒 lflushCommitLogTimed=
false,是否定時刷盤,
預設為實時刷盤,詳細請參考
CommitLog lflushIntervalConsumeQueue= 1000,消費隊列刷盤間隔,
預設為1秒 lfileReservedTime= 72,檔案保留時間(機關小時),
預設為3天 ldeleteWhen= “04”,何時觸發删除檔案,
預設淩晨4點删除檔案 lBrokerRole brokerRoleBrokerRole.ASYNC_MASTER,broker的角色:異步複制的master,同步雙寫的master,slave
lflushDiskTypeFlushDiskType.ASYNC_FLUSH,刷盤:同步,異步
lsyncFlushTimeout同步刷盤逾時時間,預設為5秒
l13 messageDelayLevel定時消息級别,預設為1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m
9m 10m 20m 30m 1h 2h分别對應1~18級
同一個訂閱組内不同Consumer執行個體訂閱不同topic消費混亂問題分析說明
兩個應用的消費者使用相同的consumer group,但消費不同的topic,造成兩個應用各有一半消息丢失。原因:offset是共用的,offset隻與groupname有關。如下官方文檔截圖:
參考資料:
http://blog.csdn.net/a417930422/article/details/52585548