kafka源碼閱讀-【1、概念介紹】

1、kafka介紹

kafka是一種分佈式,發佈/訂閱消息系統,基於Scala語言實現。爲什麼使用Scala語言?傳言是作者剛好在學習Scala,所以才使用Scala。kafka具有快速可擴展可持久化等特點。kafka最初由LinkedIn開發,並於2011年初開源,2012年從Apache孵化器畢業,成爲Apache基金會頂級項目。隨着時間發展,越來越多公司的大型分佈式系統支持與kafka集成,例如:Apache StormSpark等等,也有越來越多的公司基於kafka建立起近乎實時的信息處理平臺,例如:LinkedInNetfixUberVerizon。在國內也有很多互聯網公司在生產環境使用kafka作爲其消息中間件。

kafka之所以收到大家的追捧主要有以下幾個原因:

  • kafka具有幾乎實時性的消息處理能力,即使面對海量數據也能高效的存儲消息和查詢消息。kafka將消息保存在磁盤,通過順序讀寫的方式,提高了磁盤的訪問能力。
  • kafka支持批量處理消息,同時也支持批量的消息壓縮,無論是生產者消費者服務端,都能批量處理消息,而不是一個一個消息處理,這樣能有效的提高kafka本身的吞吐量,同時也提高了壓縮效率。
  • kafka支持消息分區,每個分區中保證消息的順序傳遞,不同的分區之間是獨立的,可以達到負載均衡的效果,也能提高kafka的吞吐量。
  • kafka支持在線增加分區,支持在線水平擴展。
  • kafka支持爲每個分區創建多個副本,其中只有一個Leader副本負責與客戶端獨寫,其它副本只負責與Leader副本進行同步,這種方式提高了數據的容災能力。kafka會將Leader副本均勻的分佈在集羣中的服務器上面,實現容災性能最大化

總而言之,kafka基本上具備了:高性能高容災能力高吞吐量近實時性數據持久化同分區順序保證異步通信,等等特點,同時嫩在微服務盛行的年代,kafka能讓服務與服務之間解耦合,從而實現系統間的高內聚低耦合。

2、核心概念

下面開始介紹kafka有關的基本概念

2.1、消息

消息是kafka基本數據單元。消息由一串字節構成,其中主要由keyvalue構成,key和value也都是byte數組。key的主要作用是根據一定策略,將此消息路由到指定的分區中,這樣就可以保證包含同一key的消息全部寫入同一個分區中,key可以是null。消息的真正有效負載是value部分的數據。爲了提高網絡的存儲的利用率,生產者會批量發送消息到kafka,並在發送之前對消息進行壓縮,具體的細節在本書後面的章節會詳細介紹。
如下圖所示:
在這裏插入圖片描述

2.2、Topic 與 Log

Topic是用於劃分消息所屬的邏輯概念,是一種消息體的集合,可以類比表結構中的表。每個Topic可以有多個生產者向其推送消息(Push),也可以有多個消費者消息其消息,如下圖所示:
在這裏插入圖片描述

  • 每個Topic可以劃分多個分區(partition),同一個Topic下的不同分區包含的消息是不同的。每個消息在被添加到分區時,都會被分配一個offset,它是消息在此分區中的唯一編號,kafka通過offset保證消息在分區內的順序,offset的順序性不跨分區,即kafka只能保證在同一個分區底下的消息是有序的;同一個topic底下的不同分區並不能保證其順序性。

  • 同一個Topic的不同分區會分配在不同的Broker上面(下面會介紹)。分區是kafka水平擴展的基礎,我們可以通過增加服務器的partition來進行橫向擴展,來提高kafka的吞吐量。

  • 分區在邏輯上對應着一個Log,生產者將消息寫入分區的時候,其實是先寫入分區對應的Log。Log是一個邏輯概念,每個Log都對應着磁盤上的一個文件夾。Log由多個Segment組成,每個Segment對應着一個日誌文件索引文件。在面對海量數據的時候,爲了避免出現超大文件,會對日誌文件進行切分,當數據大小超過文件最大大小,會生成一個新的Segment繼續提供寫入操作。

  • 此外因爲kafka是順序IO,所以只向着最新的Segment寫入數據。爲了權衡文件大小,索引速度、佔用內存大小等多方面因素,索引文件採用稀疏索引的方式,佔用內存不大,可以將索引緩存在內存中,以便提高效率。

2.3、保留策略 與 日誌壓縮

無論消費者是否已經消費了消息,kafka都會一直保存着這些消息,但並不會像數據庫那樣長期持久化。爲了避免磁盤被沾滿,kafka會配置相應的保留策略,以實現週期性的刪除歷史消息。 kafka有兩種保留策略:按照消息保留時間按照Topic數據大小

  • 按照消息保留時間,當消息在kafka中保存的時間超時其指定的時間限制時,就會被後臺線程刪除。
  • 按照Topic數據大小,當Topic所佔的日誌文件大小大於一個閾值的時候,則後臺線程會從最舊的消息開始刪除。

這兩種策略配置也比較靈活,可以全局配置也可以部分Topic進行配置。

此外kafka還會進行日誌壓縮,主要是針對消息的value進行壓縮,當開啓kafka的日誌壓縮功能,kafka會在後臺開啓一個線程,定期將相同key的消息進行合併,只保留最新的值(我個人理解爲冪等處理),但是近期正在發送的消息,並不會被合併,因爲後臺線程來不及。

2.4、Broker 與 副本

  • broker 是一個單獨的kafka 服務端就是一個broker。broker主要任務就是接收生產者發送過來的消息,分配offset,之後保存到磁盤上;同時,接收消費者,以及其它broker的請求,根據請求類型進行相應的處理後返回響應。在一般的生產環境中,一個Broker獨佔一臺物理機器。

  • 副本 是kafka對消息進行了冗餘,每個partition可以有多個副本,每個副本中包含的消息是一樣的 (前提是offset不超過HW)。每個分區至少有一個副本,當分區中只有一個副本的時候,只有Leader副本,沒有Follower副本。此外每個副本集合中,都會選擇出一個副本作爲Leader,kafka在不同的情況下會選擇不同的選舉策略。當前客戶端請求到該partition都由Leader副本進行處理響應,Follower負責同步Leader,如下圖所示:
    在這裏插入圖片描述

2.5、ISR集合

ISR集合表示的是目前可用的消息量與Leader相差不多的可用副本集合,這是整個副本集合的子集。要符合屬於ISR集合的副本需要滿足兩個條件:

  • 副本所在節點必須維持着和Zookeeper的連接。
  • 副本最後一條消息的offset與lLeader副本的最後一條消息的offset之間的差值不能超過閾值。

ISR集合由每個partitionLeader來維護。所有的請求會統一發送到Leader副本處理,然後Follower會從Leader上拉取消息,整個過程是是有延遲的,所以會出現Follower上的offset略少於Leader,但只要沒超過閾值都是可以接受的。但是如果其中某一臺機器發生了動盪,比如掉線或者GC等等,必然會導致消息差距拉大,甚至超過閾值,這個時候Leader會將該Follower機器踢出ISR集合。往後,如果該Follower恢復狀態,並且成功同步消息並且追上Leader,這個時候Leader會將其重新納入ISR集合中,通過利用ISR集合的邏輯,巧妙中和了同步複製異步複製的特點。

  • 同步複製 由於所有副本都需要同步複製,如果出現一個副本宕機了,會導致整個副本集羣被拖垮
  • 異步複製 雖然異步複製不會導致副本集羣被拖垮的情況,但是如果Follower全部都沒有跟上Leader此時,Leader宕機必然也會導致消息丟失的情況。

2.6、HW 與 LEO

  • HW(俗稱高水位)和LEO以及上面提到的ISR集合密切相關。HW標記了一個特殊的offset,當消費者消費消息的時候,只能拉取到不大於HW的offset的消息,HW之後的消息對消費者不可見。同樣HW也是由Leader副本管理的。當ISR集合中全部的Follower副本都拉取到HW當前指定的消息後,Leader副本纔會遞增HW的值,kafka官方稱這種方式爲commit,其含義是消息在多個副本中存在,當Leader遭到損壞的時候也不會出現數據丟失。

  • LEO(Log End Offset)是每個副本都會有的一個offset標記,它標記的是當前副本的最後一個消息的offset。當有生產者生產消息的時候,LEO標記會遞增,同時當Follower同步到來自Leader的消息的時候LEO也會遞增。
    下圖是一個描述HW和LEO關係的示意圖:
    在這裏插入圖片描述

2.7、Cluster 與 Controller

多個Broker可以做成 一個Cluster集羣對外提供服務,每個Cluster當中會選舉出一個Broker來擔任Controller,Controller是kafka集羣的指揮中心,而其它Broker則聽從Controller的調度實現相應的功能。Controller負責管理集羣的:分區中副本的狀態監聽zookeeper變化選舉等工作。Controller是一主多從的結構,所有的Broker都會監聽Controller Leader的狀態,當Leader Controller出現故障的時候,會重新選舉Controller Leader。

2.8、生產者

生產者,想必很多人都熟悉,(Producer)其主要工作是負責生產消息,並將消息按照一定的規則發送(push)到Topic的分區上,(自定義partition策略)。生產者可以更具自己的需要去實現或者選擇消息的分區方式。

2.9、消費者 與 消費者組

  • 消費者(Consumer)的主要工作是從Topice(pull)拉取消息,並對消息進行消費。某個消費者消費到parttion的哪個位置的相關信息,是Consumer自己維護的,此外通過pull的方式可以避免消費者被消息壓垮的情況。

  • 消費者組(Consumer Group)是由多個消費者同時組成的一個組集合,一個Consumer只能同時存在一個組內,在消費組內,Topic的分區(partition)會根據當前組的消費者情況,進行一個分配,讓每一個消費者都能消費屬於自己的一個或者多個組。在組內,一個消息只能被一個消費者消費,但是在組與組之間,一條消息會被多個組的一個消費者消費到,通過這種方式,可以很靈活的切換爲廣播,和點對點的方式進行消息消費。如下圖所示 (官方圖片)
    在這裏插入圖片描述
    (圖中的p0,p1,p2,p3來源同一個topic的不同分區)

  • 重平衡(rebalance)從上圖中也可以看出,kafka消費者組的消費者數量是可變化的,當有2個消費者和4個消費者,每個消費者消費的分區和其數量也是不一樣的,爲了達到這一狀態,kafka內部有機制進行分區 分配 (後面的文章會詳細介紹),當然消費者的數量也不是一成不變的,可能會出現消費者的上線或者下線。每當發生消費者數量變化,或者topic分區變化 *(增加partition)*的時候,原有的分配結果會被打破,需要爲每個消費者重新分配分區,其中這個過程就是 重平衡

3、總結

本篇文章介紹了kafka的一些基本概念,同時也簡單介紹了爲什麼kafka會有那麼高的吞吐量,同時爲後面的文章做鋪墊。那麼整體來說kafka的可以用如下幾個官網的圖片來闡述。

首先,kafka的Topic是多分區的(橫向拓展),每個分區的不同副本爲了高可用,分配在不同的broker機器上面,如下圖:
在這裏插入圖片描述
其次,生產者通過其自身的分區策略,將消息發送到不同的分區(實現了Topic的橫向拓展):
在這裏插入圖片描述
最後每個consumer group通過分配策略,讓其consumer消費其中的一個或者幾個分區,並且分配策略會隨着消費者數量的變化而變化:
在這裏插入圖片描述
後面的文章也會陸續到來

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