kafka深入解讀

不經意間,看到某大佬的公衆號文章深有感觸,於是乎把大佬的專業術語搬上來,加上自己的大白話,做點總結。

Kakfa起初是由LinkedIn公司開發的一個分佈式的消息系統,後成爲Apache的一部分,它使用Scala編寫,以可水平擴展和高吞吐率而被廣泛使用。目前越來越多的開源分佈式處理系統如Cloudera、Apache Storm、Spark等都支持與Kafka集成。Kafka憑藉着自身的優勢,越來越受到互聯網企業的青睞,很多公司採用Kafka作爲其內部核心消息引擎之一。

Kafka作爲一個商業級消息中間件,消息可靠性的重要性可想而知。

1. 如何確保消息的精確傳輸?

2. 如何確保消息的準確存儲?

3. 如何確保消息的正確消費?

這些都是需要考慮的問題。首先從Kafka的架構着手,先了解下Kafka的基本原理,然後通過對kakfa的存儲機制、複製原理、同步原理、可靠性和持久性保證等等一步步對其可靠性進行分析,最後通過benchmark來增強對Kafka高可靠性的認知。

一.  Kafka體系架構

如上圖所示,一個典型的Kafka體系架構包括若干Producer(可以是服務器日誌,業務數據,頁面前端產生的page view等等),若干broker(Kafka支持水平擴展,一般broker數量越多,集羣吞吐率越高),若干Consumer (Group),以及一個Zookeeper集羣。Kafka通過Zookeeper管理集羣配置,選舉leader,以及在consumer group發生變化時進行rebalance。Producer使用push(推)模式將消息發佈到broker,Consumer使用pull(拉)模式從broker訂閱並消費消息。

名詞解釋:

1.  broker:  消息中間件處理節點,一個Kafka節點就是一個broker,一個或多個Broker可以組成一個Kafka集羣。

2. Topic:Kafka根據topic對消息進行歸類,發佈到Kafka集羣的每條消息都需要指定一個topic。

3. Producer:消息生產者,向Broker發送消息的客戶端。

4. Consumer:消息消費者,從Broker讀取消息的客戶端。

5. Consumer Group:每個Consumer屬於一個特定的Consumer Group。一條消息可以發送到多個不同的Consumer Group,但是一個Consumer Group中只能有一個Consumer消費一個partition。

6. Partition:物理上的概念,一個Topic可以分成多個partition,每個partition內部都是有序的。

 對Topic & Partition的解釋:

一個topic可以認爲一個一類消息,每個topic將被分成多個partition,每個partition在存儲層面是append log文件。任何發佈到此partition的消息都會被追加到log文件的尾部,每條消息在文件中的位置稱爲offset(偏移量),offset爲一個long型的數字,它唯一標記一條消息。每條消息都被append到partition中,是順序寫磁盤,因此效率非常高(經驗證,順序寫磁盤效率比隨機寫內存還要高,這是Kafka高吞吐率的一個很重要的保證)。

每一條消息被髮送到broker中,會根據partition規則選擇被存儲到哪一個partition。如果partition規則設置的合理,所有消息可以均勻分佈到不同的partition裏,這樣就實現了水平擴展。(如果一個topic對應一個文件,那這個文件所在的機器I/O將會成爲這個topic的性能瓶頸,而partition解決了這個問題)。在創建topic時可以在  $KAFKA_HOME/config/server.properties  中指定這個partition 的數量(如下所示),當然可以在topic創建之後去修改partition的數量。

# The default number of log partitions per topic. More partitions allow greater
# parallelism for consumption, but this will also result in more files across
# the brokers.

num.partitions=3

在發送一條消息時,可以指定這個消息的key,producer 根據這個key和partition機制來判斷這個消息發送到哪個partition。partition機制可以通過指定producer的  partition.class  這一參數來指定,該class必須實現 kafka.producer.Partitioner 接口。

二.  高可靠性存儲分析

Kafka的高可靠性的保障來源於其健壯的副本(replication)策略。通過調節其副本相關參數,可以使得Kafka在性能和可靠性之間運轉的遊刃有餘。Kafka從0.8.x版本開始提供partition級別的複製,replication的數量可以在    $KAFKA_HOME/config/server.properties  中配置(default.replication.refactor)。

這裏先從Kafka文件存儲機制入手,從最底層瞭解Kafka的存儲細節,進而對其的存儲有個微觀的認知。之後通過Kafka複製原理和同步方式來闡述宏觀層面的概念。最後從ISR,HW,leader選舉以及數據可靠性和持久性保證等等各個維度來豐富對Kafka相關知識點的認知。

2.1 Kafka文件存儲機制

Kafka中消息是以topic進行分類的,生產者通過topic向Kafka broker發送消息,消費者通過topic讀取數據。然而topic在物理層面又能以partition爲分組,一個topic可以分成若干個partition,那麼topic以及partition又是怎麼存儲的呢?partition還可以細分爲segment,一個partition物理上由多個segment組成,那麼這些segment又是什麼呢?下面我們來一一揭曉。

爲了便於說明問題,假設這裏只有一個Kafka集羣,且這個集羣只有一個Kafka broker,即只有一臺物理機。在這個Kafka broker中配置($KAFKA_HOME/config/server.properties中)log.dirs=/tmp/kafka-logs,以此來設置Kafka消息文件存儲目錄,與此同時創建一個topic:topic_test,partition的數量爲4。

$KAFKA_HOME/bin/kafka-topics.sh  –create –zookeeper localhost:2181 –partitions 4  –topic topic_test   –replication-factor 4。那麼我們此時可以在/tmp/kafka-logs目錄中可以看到生成了4個目錄:

drwxr-xr-x 2 root root 4096 Apr 10 16:10 topic_test-0
drwxr-xr-x 2 root root 4096 Apr 10 16:10 topic_test-1
drwxr-xr-x 2 root root 4096 Apr 10 16:10 topic_test-2
drwxr-xr-x 2 root root 4096 Apr 10 16:10 topic_test-3

在Kafka文件存儲中,同一個topic下有多個不同的partition,每個partiton爲一個目錄,partition的名稱規則爲:topic名稱+有序序號,第一個序號從0開始計,最大的序號爲partition數量減1,partition是實際物理上的概念,而topic是邏輯上的概念。

2.1.1.  segment

上面提到partition還可以細分爲segment,這個segment又是什麼?如果就以partition爲最小存儲單位,我們可以想象當Kafka producer不斷髮送消息,必然會引起partition文件的無限擴張,這樣對於消息文件的維護以及已經被消費的消息的清理帶來嚴重的影響,所以這裏以segment爲單位又將partition細分。每個partition(目錄)相當於一個巨型文件被平均分配到多個大小相等的segment(段)數據文件中(每個segment 文件中消息數量不一定相等)這種特性也方便old segment的刪除,即方便已被消費的消息的清理,提高磁盤的利用率。每個partition只需要支持順序讀寫就行,segment的文件生命週期由服務端配置參數(log.segment.bytes,log.roll.{ms,hours}等若干參數)決定。

segment文件由兩部分組成,分別爲“.index”文件和“.log”文件,分別表示爲segment索引文件和數據文件。這兩個文件的命令規則爲:partition全局的第一個segment從0開始,後續每個segment文件名爲上一個segment文件最後一條消息的offset值,數值大小爲64位,20位數字字符長度,沒有數字用0填充,如下:

00000000000000000000.index
00000000000000000000.log
00000000000000170410.index
00000000000000170410.log
00000000000000239430.index
00000000000000239430.log

以上面的segment文件爲例,展示出segment:00000000000000170410的“.index”文件和“.log”文件的對應的關係,如下圖:

如上圖,“.index”索引文件存儲大量的元數據,“.log”數據文件存儲大量的消息,索引文件中的元數據指向對應數據文件中message的物理偏移地址。其中以“.index”索引文件中的元數據[3, 348]爲例,在“.log”數據文件表示第3個消息,即在全局partition中表示170410+3=170413個消息,該消息的物理偏移地址爲348。

那麼如何從partition中通過offset查找message呢?

以上圖爲例,讀取offset=170418的消息,首先查找segment文件,其中00000000000000000000.index爲最開始的文件,第二個文件爲00000000000000170410.index(起始偏移爲170410+1=170411),而第三個文件爲00000000000000239430.index(起始偏移爲239430+1=239431),所以這個offset=170418就落到了第二個文件之中。其他後續文件可以依次類推,以其實偏移量命名並排列這些文件,然後根據二分查找法就可以快速定位到具體文件位置。其次根據00000000000000170410.index文件中的[8,1325]定位到00000000000000170410.log文件中的1325的位置進行讀取。

要是讀取offset=170418的消息,從00000000000000170410.log文件中的1325的位置進行讀取,那麼怎麼知道何時讀完本條消息,否則就讀到下一條消息的內容了?

這個就需要聯繫到消息的物理結構了,消息都具有固定的物理結構,包括:offset(8 Bytes)、消息體的大小(4 Bytes)、crc32(4 Bytes)、magic(1 Byte)、attributes(1 Byte)、key length(4 Bytes)、key(K Bytes)、payload(N Bytes)等等字段,可以確定一條消息的大小,即讀取到哪裏截止。

三. 複製原理和同步方式

Kafka中topic的每個partition有一個預寫式的日誌文件,雖然partition可以繼續細分爲若干個segment文件,但是對於上層應用來說可以將partition看成最小的存儲單元(一個有多個segment文件拼接的“巨型”文件),每個partition都由一些列有序的、不可變的消息組成,這些消息被連續的追加到partition中。

上圖中有兩個新名詞:HW和LEO。這裏先介紹下LEO,LogEndOffset的縮寫,表示每個partition的log最後一條Message的位置。HW是HighWatermark的縮寫,是指consumer能夠看到的此partition的位置,這個涉及到多副本的概念,這裏先提及一下,下節再詳表。

言歸正傳,爲了提高消息的可靠性,Kafka每個topic的partition有N個副本(replicas),其中N(大於等於1)是topic的複製因子(replica fator)的個數。Kafka通過多副本機制實現故障自動轉移,當Kafka集羣中一個broker失效情況下仍然保證服務可用。在Kafka中發生複製時確保partition的日誌能有序地寫到其他節點上,N個replicas中,其中一個replica爲leader,其他都爲follower, leader處理partition的所有讀寫請求,與此同時,follower會被動定期地去複製leader上的數據。

如下圖所示,Kafka集羣中有4個broker, 某topic有3個partition,且複製因子即副本個數也爲3:

Kafka提供了數據複製算法保證,如果leader發生故障或掛掉,一個新leader被選舉並被接受客戶端的消息成功寫入。Kafka確保從同步副本列表中選舉一個副本爲leader,或者說follower追趕leader數據。leader負責維護和跟蹤ISR(In-Sync Replicas的縮寫,表示副本同步隊列,具體可參考下節)中所有follower滯後的狀態。當producer發送一條消息到broker後,leader寫入消息並複製到所有follower。消息提交之後才被成功複製到所有的同步副本。消息複製延遲受最慢的follower限制,重要的是快速檢測慢副本,如果follower“落後”太多或者失效,leader將會把它從ISR中刪除。

對於ISR和HW或者太深奧,或者自己太愚笨,待研究後再詳述。

 

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