1. 程式人生 > >消息隊列之kafka(核心架構)

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

存儲陣列 所有 工具 link 數據文件 file sum 當前 都是

1. Kafka的經典架構

技術分享圖片
 Kafka是LinkedIn 用於日誌處理的分布式消息隊列,同時支持離線和在線日誌處理。
 Kafka 對消息保存時根據 Topic 進行歸類。
 發送消息者就是Producer,消息的發布描述為Producer
 消息接受者就是 Consumer,消息的訂閱描述為 Consumer
 每個 Kafka 實例稱為 Broker,將中間的存儲陣列稱作 Broker(代理),Broker也是kafka集群的節點

2.架構的角色介紹

  (1)broker

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

  broker也就是中間的存儲隊列的節點實例。我們將消息發布者稱為:Produce,將消息的訂閱者稱為:Consumer,將中間的存儲陣列稱為broker。

  (2)topic

  每條發布到kafka集群的消息都有一個類別,這個類別被成為Tpoic。物理上不同的topic的消息分開存儲,邏輯上一個topic的消息雖然保存與一個或者多個broker中。但用戶只需要指定消費的topic,即生產或者消費數據的客戶端不需要關心數據存儲與何處。
  kafka中發布訂閱的對象就是topic。為每一個數據類型創建一個topic,把向topic發布消息的客戶端稱為producer,從topic訂閱消息的客戶端稱為consumer,producer和consumer可以同時從多個topic讀寫數據。一個kafka集群由一個或者多個broker服務器組成。他負責持久化和備份具體的kafka消息。

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

  (3)partition

技術分享圖片
  partition是物理的概念,每一個topic包含一個或者多個partition。
  topic的分區策略(針對寫數據的時候進行分區):
    - 輪詢:順序分發,僅針對於message沒有key的時候。
    - Hash分區:在message有key的情況下,(key.hash%分區個數)。如果在增加分區的時候,partition裏面的message不會重新進行分配,隨著數據的繼續寫入,這個新的分區才會參與load balance。


  topic的分區邏輯存儲方式
技術分享圖片
   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數量

  (4)Producer

   負責主動發布消息到kakfa broker(push)
   kafka消息的保存策略:每個 Topic 被分成多個 partition(區)。每條消息在 partition 中的位置稱為 offset(偏移量),類型為 long 型數字。消息即使被消費了,也不會被立即刪除, 而是根據 broker 裏的設置(基於時間存儲或者基於大小),保存一定時間後再清除,比如 log 文件設置存儲兩天,則兩天後, 不管消息是否被消費,都清除。

  (5)Consumer

   消息消費者,向kafkabroker讀取消息的客戶端。(pull)
   消費消息的策略:(使用的是roundrabin算法):如果有4個分區,現在有三個消費者線程,那麽這個三個線程一人分一個分區消費,最後一個分區以輪詢的方式,發送給第一個線程消費,如果此時又多加入一個線程,那麽就會將第4個分區就分給新加入的線程消費,如果有一個線程退出,那麽第三個和第四個分區也會以輪詢的方式,發送給第一個線程和第二個線程消費。(kafka內部自動維護這個負載均衡)。
   消費的原則:一個consumer對一個partition中的一條數據只需要消費一次,每一個consumer組維護一個下標文件,叫做offset,這個offset用於記錄當前的consumer組消費數據的下標,每進行消費一條數據,當前的offset就會遞增1(offset之前的數據,都表示已經消費過的數據)。

  (6)Consumer group

技術分享圖片
   一個consumer group 包含多個consumer,這個是預先在配置文件中配置好的。各個consumer可以組成一個租,partition中的每一個message只能被一個組中的一個consumer進行消費,其他的consumer不能消費同一個topic中同一個分區的數據,不同組的consumer可以消費同一個topic的同一個分區的數據。
    廣播和單播
     廣播:所有的consumer每一個consumer劃分一組
     單播:所有的consumer劃分一組(一組中只允許一個消費)
    對於kafka消費的總結
      - 一個分區只能被一個消費者組中的一個成員消費
      - 一個成員可以消費一個topic的多個分區
      - 一個 Topic 中的每個 Partition 只會被一個“Consumer group”中的一個 Consumer 消費
      - 一個成員還可以消費另外一個topic的分區

  (7)segment

    在kafka文件存儲找中,同一個topic下有多個partition,每一個partition為一個目錄,partition命名規則為:topic 名稱+有序序號,第一個partition序號從0開始,序號最大值為partitions數量-1,partition物理上由多個segment組成,每一個segment存儲著多個message信息(默認是:1G),而每一個message是由一個key-value和一個時間戳組成。
    segment文件的生命周期由服務器配置參數決定:默認的是168個小時後刪除。
    segment由兩大部分組成: index filedata file,這2個文件一一對應,成對出現,後綴".index"和".log"分別表示為 segment 索引文件、數據文件。
技術分享圖片
    segment的命名規則:partion 全局的第一個 segment 從 0 開始,後續每個 segment 文件名為上一個 segment 文件最後一條消息的 offset 值。數值最大為 64 位 long 大小,19 位數字字符長度,沒有數字用 0 填充。(每一個partition都是如此)
    segment的index file: 索引文件存儲大量元數據,數據文件存儲大量消息,索引文件中元數據指向對應數據文件中 message 的物理偏移地址。
技術分享圖片
    segment的data file
技術分享圖片


kafka讀取數據的查找message的步驟
以讀取 offset=368776 的 message,需要通過下面 2 個步驟查找。
技術分享圖片
第一步: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。

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