kafka 初學筆記

1. 概念分析

    broker: 消息處理結點, 1個broker就是一個kafka服務進程或者服務器,多個broker組成kafka集羣。

    topic: 消息主題,所有的消息按照主題歸類存儲,每個topic會在broker上生成一個文件夾。
    partition: topic的物理分組,一個topic可以設置多個partition。每個partition服務一個consumer,所以如果consumer數量超過partition數量,多出的consumer無法讀到任何數據。例如,創建一個topic "haha",會在logs下面多出3個文件夾:haha-0, haha-1, haha-2。很明顯,文件夾的名稱格式是:topic-particion序號。但有一個問題大家都會問,producer往生產一個topic的消息,這條消息應該放到哪個partition中呢?key,消息key的作用就在此。根據key做哈希,最後根據哈希結果決定這條消息放哪個partition。假如說沒有設置key,那就輪詢分區決定。

    replication:分區可以有多個replication,這是broker級別的對partition做的replication。假如replication爲3,那麼每個partition都應該分別存在與3個broker中。但不一定每個broker都擁有所有的partition。

    segment: 爲了快速查找到消息,系統將一個partition的數據分成多個segment存儲。每個segment有大小限制,超過限制,系統會新建一個segment。系統接收到provider傳
傳來的消息時,會先將消息保存在內存的一個數據結構中,有另外一個線程,每隔一段時間(1秒,可配置)將內存中的消息flush到磁盤。只有磁盤中的數據,才能被consumer訪問。

    offset: 一個連續的用於定位被追加到分區的每一個消息的序列號,最大值爲64位的long大小,19位數字字符長度。這個offset說白了是某個consumer讀取某個partition的最新位置,這個consumer必須是與那個partition關聯的。consumer不可能一直在線,有可能掛掉,那麼重啓的時候consumer難道要從頭開始讀取消息?所以kafka乾脆把consumer的讀取進度,也就是offset乾脆保存在server端。至於保存方式,可以保存在zookeeper中,我們可以通過在zk命令行中執行:get /consumers/jd-group/offsets/haha/0 來查看group ID爲jd-group,topic爲haha,partition爲0的segment。爲什麼是group?因爲kafka將consumer按group管理,一個group訪問一個partition。至於同一個group的各個consumer,只能相互競爭了。但是,用zookeeper來記錄offset,性能很容易到達瓶頸,因爲zk並不適合大批量頻繁的寫操作。新版Kafka已推薦將consumer的位移信息保存在Kafka內部的topic中,即__consumer_offsets topic,並且默認提供了kafka_consumer_groups.sh腳本供用戶查看consumer信息。

    其實,這幾個概念(尤其是segment)關乎到kafka的核心——存儲。kafka是基於磁盤存儲的,而不是內存。我一開始也很納悶,磁盤讀寫效率不是很低嗎,kafka如何做到高吞吐量的?其實磁盤的順序讀寫效率,是和內存的隨機讀寫效率是同一個級別的。而且,用磁盤存儲數據,可以持久化。
    
    segment是如何讓kafka有高吞吐量的呢?
    
    首先是文件命名,它關係到如何定位到哪個segment的問題,segment利用了消息的offset,每一個segment的文件名是前一個segment中最後一個消息的offset。所以第1個segment的文件名是00000000000000000000,如果這個segment中存放了856個消息,那麼下一個segment的文件名就是00000000000000000856,依次類推。所以,要讀取某個offset時,只要對segment的文件列表做二分查找,很快就能找到消息所在的對應segment中。
    其次,定位了segment之後,如何又在segment中快速找到消息呢?setment的文件不是一個,其實是4個:log, index, timeindex, snapshot。主要是log 和 index。log存放消息的數據,index存放這些數據的索引,索引格式是:<offset, position>,即每個offset對應的消息,在log文件中的具體位置。所以,要在segment中獲取到某個offset的消息數據,首先需要遍歷index文件,查找到對應的offset的那條索引,然後找到對應的position,然後再讀取log文件position位置的數據,就可以找到了。因爲index文件很小,所以遍歷index文件不會有太大的性能影響。
    
    下面是一個broker下的log文件目錄:
    
        
    ${log.dir}
        |__ __consumer_offsets-0
        |  |__ 00000000000000000000.index
        |  |__ 00000000000000000000.log
        |  |__ 00000000000000000000.timeindex
        |  |__ leader_epoch_checkpoint
        |__ __consumer_offsets-1
        
        ......
        
        |__ __consumer_offsets-49
        
        |__ haha-0
           |__ 00000000000000000000.index
           |__ 00000000000000000000.log
           |__ 00000000000000000000.timeindex
           |__ 00000000000000034567.index
           |__ 00000000000000034567.log
           |__ 00000000000000034567.timeindex
           |__ 00000000000000078901.index
           |__ 00000000000000078901.log
           |__ 00000000000000078901.timeindex
           
           ...
           
        |__ haha-1
           |__ 00000000000000000000.index
           |__ 00000000000000000000.log
           |__ 00000000000000000000.timeindex
        |__ haha-2
           |__ 00000000000000000000.index
           |__ 00000000000000000000.log
           |__ 00000000000000000000.timeindex
           
    __consumer_offsets是kafka默認的topic,默認有50個partition,但都在同一個kafka服務器上,它用來替代使用zookeeper記錄offset。
    
    一個簡單的概念分析到此結束,通過將這幾個概念徹底理解透,對於深入探索kafka至關重要。

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