天天看點

消息隊列之kafka(核心架構)

消息隊列之kafka(核心架構)

 Kafka是LinkedIn 用于日志處理的分布式消息隊列,同時支援離線和線上日志處理。

 Kafka 對消息儲存時根據 Topic 進行歸類。

 發送消息者就是Producer,消息的釋出描述為Producer

 消息接受者就是 Consumer,消息的訂閱描述為 Consumer

 每個 Kafka 執行個體稱為 Broker,将中間的存儲陣列稱作 Broker(代理),Broker也是kafka叢集的節點

  kafka叢集包括一個或者多個伺服器,這種伺服器被稱為brker。

  broker也就是中間的存儲隊列的節點執行個體。我們将消息釋出者稱為:Produce,将消息的訂閱者稱為:Consumer,将中間的存儲陣列稱為broker。

  每條釋出到kafka叢集的消息都有一個類别,這個類别被成為Tpoic。實體上不同的topic的消息分開存儲,邏輯上一個topic的消息雖然儲存與一個或者多個broker中。但使用者隻需要指定消費的topic,即生産或者消費資料的用戶端不需要關心資料存儲與何處。

  kafka中釋出訂閱的對象就是topic。為每一個資料類型建立一個topic,把向topic釋出消息的用戶端稱為producer,從topic訂閱消息的用戶端稱為consumer,producer和consumer可以同時從多個topic讀寫資料。一個kafka叢集由一個或者多個broker伺服器組成。他負責持久化和備份具體的kafka消息。

  topic就是資料的主題,是資料記錄釋出的地方,可以用來區分業務系統。kafka中的topics總是多訂閱者模式,一個topic可以擁有一個或者多個消費者來訂閱它的資料。

消息隊列之kafka(核心架構)

  partition是實體的概念,每一個topic包含一個或者多個partition。

  topic的分區政策(針對寫資料的時候進行分區):

    - 輪詢:順序分發,僅針對于message沒有key的時候。

    - Hash分區:在message有key的情況下,(key.hash%分區個數)。如果在增加分區的時候,partition裡面的message不會重新進行配置設定,随着資料的繼續寫入,這個新的分區才會參與load balance。

  topic的分區邏輯存儲方式:

消息隊列之kafka(核心架構)

   topic 會分成一個或多個 partition,每個 partiton 相當于是一個 子 queue。在實體結構上,每個 partition 對應一個實體的目錄(檔案夾),檔案夾命名是 [topicname][partition][序号],一個 topic 可以有無數多的 partition,根據業務需求和資料量 來設定。在 kafka 配置檔案中可随時更高 num.partitions 參數來配置更改 topic 的 partition 數 量,在建立 Topic 時通過參數指定 parittion 數量。Topic 建立之後通過 Kafka 提供的工具也可以修改 partiton 數量。分區中存放着資料本身和資料的index下标。在向partition寫入資料的時候,是順序寫入的,每一個資料寫入的時候都會有一個類似下标的東西(index),随着資料的寫入而增長。partition也是叢集負載均衡的基本機關。

  總結:

    - 一個topic的partition數量大于等于broker的數量,可以提高吞吐率。

    - 同一個partition的Replica盡量分散到不同的機器上,高可用。

    - kafka的分區數:(1|2|3 + 0.95) * broker數量

   負責主動釋出消息到kakfa broker(push)

   kafka消息的儲存政策:每個 Topic 被分成多個 partition(區)。每條消息在 partition 中的位置稱為 offset(偏移量),類型為 long 型數字。消息即使被消費了,也不會被立即删除, 而是根據 broker 裡的設定(基于時間存儲或者基于大小),儲存一定時間後再清除,比如 log 檔案設定存儲兩天,則兩天後, 不管消息是否被消費,都清除。

   消息消費者,向kafkabroker讀取消息的用戶端。(pull)

   消費消息的政策:(使用的是roundrabin算法):如果有4個分區,現在有三個消費者線程,那麼這個三個線程一人分一個分區消費,最後一個分區以輪詢的方式,發送給第一個線程消費,如果此時又多加入一個線程,那麼就會将第4個分區就分給新加入的線程消費,如果有一個線程退出,那麼第三個和第四個分區也會以輪詢的方式,發送給第一個線程和第二個線程消費。(kafka内部自動維護這個負載均衡)。

   消費的原則:一個consumer對一個partition中的一條資料隻需要消費一次,每一個consumer組維護一個下标檔案,叫做offset,這個offset用于記錄目前的consumer組消費資料的下标,每進行消費一條資料,目前的offset就會遞增1(offset之前的資料,都表示已經消費過的資料)。

消息隊列之kafka(核心架構)

   一個consumer group 包含多個consumer,這個是預先在配置檔案中配置好的。各個consumer可以組成一個租,partition中的每一個message隻能被一個組中的一個consumer進行消費,其他的consumer不能消費同一個topic中同一個分區的資料,不同組的consumer可以消費同一個topic的同一個分區的資料。

    廣播和單點傳播:

     廣播:所有的consumer每一個consumer劃分一組

     單點傳播:所有的consumer劃分一組(一組中隻允許一個消費)

    對于kafka消費的總結:

      - 一個分區隻能被一個消費者組中的一個成員消費

      - 一個成員可以消費一個topic的多個分區

      - 一個 Topic 中的每個 Partition 隻會被一個“Consumer group”中的一個 Consumer 消費

      - 一個成員還可以消費另外一個topic的分區

    在kafka檔案存儲找中,同一個topic下有多個partition,每一個partition為一個目錄,partition命名規則為:topic 名稱+有序序号,第一個partition序号從0開始,序号最大值為partitions數量-1,partition實體上由多個segment組成,每一個segment存儲着多個message資訊(預設是:1G),而每一個message是由一個key-value和一個時間戳組成。

    segment檔案的生命周期由伺服器配置參數決定:預設的是168個小時後删除。

    segment由兩大部分組成: index file 和 data file,這2個檔案一一對應,成對出現,字尾".index"和".log"分别表示為 segment 索引檔案、資料檔案。

消息隊列之kafka(核心架構)

    segment的命名規則:partion 全局的第一個 segment 從 0 開始,後續每個 segment 檔案名為上一個 segment 檔案最後一條消息的 offset 值。數值最大為 64 位 long 大小,19 位數字字元長度,沒有數字用 0 填充。(每一個partition都是如此)

    segment的index file: 索引檔案存儲大量中繼資料,資料檔案存儲大量消息,索引檔案中中繼資料指向對應資料檔案中 message 的實體偏移位址。

消息隊列之kafka(核心架構)

    segment的data file:

消息隊列之kafka(核心架構)

kafka讀取資料的查找message的步驟:

以讀取 offset=368776 的 message,需要通過下面 2 個步驟查找。

消息隊列之kafka(核心架構)

第一步:00000000000000000000.index,表示最開始的檔案,起始偏移量(offset)為 0,00000000000000368769.index 的消息量起始偏移量為 368770 = 368769 + 1,00000000000000737337.index 的起始偏移量為 737338=737337 + 1,其他後續檔案依次類推。以起始偏移量命名并排序這些檔案,隻要根據 offset 二分查找檔案清單,就可以快速定 位到具體檔案。當 offset=368776 時定位到 00000000000000368769.index 和對應 log 檔案。

第二步:當 offset=368776 時,依次定位到 00000000000000368769.index 的中繼資料實體位置和 00000000000000368769.log 的實體偏移位址,然後再通過 00000000000000368769.log 順序查找直到 offset=368776 為止。查找的時候是通過相對偏移量,在.index檔案中有兩列(序列,位址),其中序列是相對偏移量:序列=查找的message的偏移量-目前檔案的起始偏移量 ,然後根據序列對應的位址,找到相應的位置上的資料message。

繼續閱讀