Kafka架構和原理


本文截取自《大數據架構詳解》。

 

Kafka架構如圖:

整個架構中包括三個角色。

  • 生產者(Producer):消息和數據生產者
  • 代理(Broker):緩存代理,Kafka的核心功能
  • 消費者(Consumer):消息和數據消費者

 整體架構很簡單,Kafka給Producer和Consumer提供注冊的接口,數據從Producer發送到Broker,Broker承擔一個中間緩存和分發的作用,負責分發注冊到系統中的Consumer。

設計要點

  Kafka非常高效,下面介紹Kafka高效的原因,對理解Kafka非常用幫助。

  1. 直接使用Linux文件系統的Cache來高效緩存數據
  2. 采用Linux Zero-Copy提高發送性能。傳統的數據發送需要發送4次上下切換,采用Sendfile系統調用之后,數據直接在內核態交換,系統上下文切換減少為2次。可以提高60%的數據發送性能。

Kafka以Topic來進行消費管理,每個Topic包含多個Part(ition),每個Part對應一個邏輯Log,由多個Segment組成。每個Segment中存儲多條消息,消息ID由邏輯位置決定,即從消息ID可直接定位到消息的存儲位置,避免ID到位置的額外映射。每個Part在內存中對應一個Index,記錄每個Segment中的第一個消息偏移。

  發布者發到某個Topic的消息會被均勻地分布到多個Part上(隨機或根據用戶指定的回調函數進行分布),Broker收到發布消息后往對應Part的最后一個Segment上添加該消息,當某個Segment上的消息條數到達配置值或消息發布時間超過閾值時,Segment上的消息便會被flush到磁盤上,只有flush到磁盤上的消息訂閱者才能訂閱到,Segment達到一定的大小后將不會再往該Segment寫數據,Broker會創建新的Segment。

  全系統分布式,即所有的Producer、Broker和Consumer都默認有多個,均為分布式的。Producer和Broker之間沒有負載均衡機制。Broker和Consumer 之間利用ZooKeeper進行負載均衡。所有的Broker和Consumer都會在Zookeeper中進行注冊,且Zookeeper會保存他們的一些元數據信息。如果某個Broker和Consumer發生了變化,那么所有其他的Broker和Consumer都會得到通知。

Kafka消息存儲方式

Topc

   Topic是發布的消息的類別或者種子Feed名。對於每個Topic,Kafka集群都會維護這個分區的Log。如圖

 

  每個分區都是一個順序的、不可變的消息隊列,並且可以持續添加。分區中的消息都被分配了一個序列號,稱之為偏移量(offset),在每個分區中此偏移量都是唯一的。

  Kafka集群保存所有的消息,直到他們過期,無論消息是否被消費。實際上,消費者所持有的僅有的元數據就是這個偏移量,也就是消費者在這個Log中的位置。在正常情況下,當消費者消費消息的時候偏移量也線性增加。但是實際偏移量由消費者控制,消費者可以重置偏移量,以重新讀取消息。

  這種設計對消費者來說操作自如,一個消費者的操作不會影響其他消費者對此Log的處理。

分區

  Kafka中采用分區的設計有兩個目的:一是可以處理更多的消息,而不受單體服務器的限制,Topic擁有多個分區,意味着它可以不受限制地處理更多數據;二是分區可以作為並行處理的單元。

  Kafka會為每個分區創建一個文件夾,文件夾的命名方式為topicName-分區序號,如圖

  而分區是由多個Segment組成的,是為了方便進行日志清理、恢復等工作。每個Segment以該Segment第一條消息的offset命名並以“.log”作為后綴。另外還有一個索引文件,他標明了每個Segment下包含的Log Entry的offset范圍,文件命名方式也是如此,以“.index”作為后綴,如下:

索引和日志文件內部的關系,如圖:

  索引文件存儲大量元數據,數據文件存儲大量消息(Message),索引文件中的元數據指向對應數據文件中Message的物理偏移地址。以索引文件中的元數據3,497為例,依次在數據文件中表示第三個Message(在全局Partition中表示第368772個message),以及該消息的物理偏移地址為497.

  Segment的Log文件由多個Message組成,下面詳細說明Message的物理結構,如圖:

 參數說明

 

如何通過offset查找Message

例如,讀取offset=368776的Message,需要通過如下兩個步驟。

第一步:查找Segment File.

00000000000000000000.index表示最開始的文件,其實偏移量(offset)為0;第二個文件00000000000000368769.index的其實偏移量為368770(368769+1),依次類推。以其實偏移量命名並排序這些文件,只要根據offset**二分查找**文件列表,就可以快速定位到具體文件。

  當offset=368776時,定位到00000000000000368769.index|log。

第二步:通過Segment File 查找Message。

  通過第一步定位到Segment File,當offset=368776時,依次定位到00000000000000368769.index的元數據物理位置和00000000000000368769.log的物理偏移地址,然后再通過00000000000000368769.log順序查找,知道offset=368776為止。

  Segment Index File采取稀疏索引存儲方式,可以減少索引文件大小,通過Linux mmap接口可以直接進行內存操作。稀疏索引為數據文件的每個對應Message設置一個元數據指針,它比稠密索引節省了更多的存儲空間,但查找起來需要消耗更多的時間。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM