Kafka之第二課


kafka存儲

Kafka的存儲佈局非常簡單。話題的每個分區對應一個邏輯日誌。物理上,一個日誌爲相同大小的一組分段文件。每次生產者發佈消息到一個分區,代理就將消息追加到最後一個段文件中。當發佈的消息數量達到設定值或者經過一定的時間後,段文件真正寫入磁盤中。寫入完成後,消息公開給消費者。
與傳統的消息系統不同,Kafka系統中存儲的消息沒有明確的消息Id。消息通過日誌中的邏輯偏移量來公開。這樣就避免了維護配套密集尋址,用於映射消息ID到實際消息地址的隨機存取索引結構的開銷。消息偏移量是增量的,但不連續。要計算下一消息的偏移量,可以在其邏輯偏移的基礎上加上當前消息的長度。
消費者始終從特定分區順序地獲取消息,如果消費者知道特定消息的偏移量,也就說明消費者已經消費了之前的所有消息。消費者向代理髮出異步拉請求,準備字節緩衝區用於消費。每個異步拉請求都包含要消費的消息偏移量。Kafka利用sendfile API高效地從代理的日誌段文件中分發字節給消費者。
這裏寫圖片描述


代理

不同於其他消息系統,kafka代理是無狀態的,即消費者必須維護已消費的狀態消息,而代理完全不管。
這種設計的創新在於:

  1. 代理以一個基於時間的SLA應用於保留策略。當消息在代理中超過一定時間後,將會被自動刪除。
  2. 消費者可以故意倒回到老的偏移量再次消費數據。雖然這違法了隊列的常見約定,但常見於許多業務中。

與zookeeper的關係

kafka使用ZooKeeper用於管理、協調代理。每個Kafka代理通過Zookeeper協調其他Kafka代理。
當Kafka系統中新增了代理或某個代理失效時,Zookeeper服務將通知生產者和消費者。生產者與消費者據此開始與其他代理協調工作。
Zookeeper在Kakfa中扮演的角色:Kafka將元數據信息保存在Zookeeper中,但是發送給Topic本身的數據是不會發到Zk上的

  • kafka使用zookeeper來實現動態的集羣擴展,不需要更改客戶端(producer和consumer)的配置。broker會在zookeeper註冊並保持相關的元數據(topic,partition信息等)更新。
  • 而客戶端會在zookeeper上註冊相關的watcher。一旦zookeeper發生變化,客戶端能及時感知並作出相應調整。這樣就保證了添加或去除broker時,各broker間仍能自動實現負載均衡。這裏的客戶端指的是Kafka的消息生產端(Producer)和消息消費端(Consumer)
  • Broker端使用zookeeper來註冊broker信息,以及監測partition leader存活性.
  • Consumer端使用zookeeper用來註冊consumer信息,其中包括consumer消費的partition列表等,同時也用來發現broker列表,並和partition
    leader建立socket連接,並獲取消息.
  • Zookeer和Producer沒有建立關係,只和Brokers、Consumers建立關係以實現負載均衡,即同一個ConsumerGroup中的Consumers可以實現負載均衡(因爲Producer是瞬態的,可以發送後關閉,無需直接等待)

kafka的設計

1、吞吐量

下一課具體介紹

2、負載均衡

  1. producer根據用戶指定的算法,將消息發送到指定的partition
  2. 存在多個partiiton,每個partition有自己的replica,每個replica分佈在不同的Broker節點上
  3. 多個partition需要選取出leadpartition,lead partition負責讀寫,並由zookeeper負責fail over
  4. 通過zookeeper管理broker與consumer的動態加入與離開

3、拉取系統

由於kafka broker會持久化數據,broker沒有內存壓力,因此,consumer非常適合採取pull的方式消費數據,具有以下幾點好處:

  1. 簡化kafka設計
  2. consumer根據消費能力自主控制消息拉取速度
  3. consumer根據自身情況自主選擇消費模式,例如批量,重複消費,從尾端開始消費等

4、可擴展性

當需要增加broker結點時,新增的broker會向zookeeper註冊,而producer及consumer會根據註冊在zookeeper上的watcher感知這些變化,並及時作出調整


設計原理

kafka的設計初衷是希望作爲一個統一的信息收集平臺,能夠實時的收集反饋信息,並需要能夠支撐較大的數據量,且具備良好的容錯能力。

持久性

kafka使用文件存儲消息,這就直接決定kafka在性能上嚴重依賴文件系統的本身特性.且無論任何OS下,對文件系統本身的優化幾乎沒有可能.文件緩存/直接內存映射等是常用的手段.因爲kafka是對日誌文件進行append操作,因此磁盤檢索的開支是較小的;同時爲了減少磁盤寫入的次數,broker會將消息暫時buffer起來,當消息的個數(或尺寸)達到一定閥值時,再flush到磁盤,這樣減少了磁盤IO調用的次數.


kafka的設計要點:

1、直接使用Linux 文件系統的cache,來高效緩存數據。
2、採用linux Zero-Copy提高發送性能。傳統的數據發送需要發送4次上下文切換,採用sendfile系統調用之後,數據直接在內核態交換,系統上下文切換減少爲2次。根據測試結果,可以提高60%的數據發送性能。Zero-Copy詳細的技術細節可以參考:https://www.ibm.com/developerworks/linux/library/j-zerocopy/
3、數據在磁盤上存取代價爲O(1)。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。
4、顯式分佈式,即所有的producer、broker和consumer都會有多個,均爲分佈式的。Producer和broker之間沒有負載均衡機制。broker和consumer之間利用zookeeper進行負載均衡。所有broker和consumer都會在zookeeper中進行註冊,且zookeeper會保存他們的一些元數據信息。如果某個broker和consumer發生了變化,所有其他的broker和consumer都會得到通知。


Kafka集羣partition replication默認自動分配分析:

下面以一個Kafka集羣中4個Broker舉例,創建1個topic包含4個Partition,2 Replication;數據Producer流動如圖所示:
(1)
這裏寫圖片描述

(2)當集羣中新增2節點,Partition增加到6個時分佈情況如下:

這裏寫圖片描述

副本分配邏輯規則如下:
  • 在Kafka集羣中,每個Broker都有均等分配Partition的Leader機會。
  • 上述圖BrokerPartition中,箭頭指向爲副本,以Partition-0爲例:broker1中parition-0爲Leader,Broker2中Partition-0爲副本。
副本分配算法如下:
  • 將所有N Broker和待分配的i個Partition排序.
  • 將第i個Partition分配到第(i mod n)個Broker上.
  • 將第i個Partition的第j個副本分配到第((i + j) mod n)個Broker上.

FYI-PPT

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章