Kafka 基礎概念及架構

一、Kafka 介紹

Kafka是⼀個分散式、分區的、多副本的、多⽣產者、多訂閱者,基於zookeeper協調的分散式⽇志系統(也可以當做MQ系統),常⻅可以⽤於web/nginx⽇志、訪問⽇志,消息服務等等。
Kafka主要應⽤場景:⽇志收集系統和消息系統

Kafka主要設計目標

  • 以時間複雜度為O(1)的⽅式提供消息持久化能⼒,即使對TB級以上數據也能保證常數時間的訪問性能。
  • ⾼吞吐率。即使在⾮常廉價的商⽤機器上也能做到單機⽀持每秒100K條消息的傳輸。
  • ⽀持Kafka Server間的消息分區,及分散式消費,同時保證每個partition內的消息順序傳輸。
  • 同時⽀持離線數據處理和實時數據處理。
  • ⽀持在線⽔平擴展

Kafka消息傳遞模式:發布-訂閱模式(不支援點對點模式)

Kafka消息推拉模式:Kafka只有消息的拉取,沒有推送,可以通過輪詢實現消息的推送

  1. Kafka在⼀個或多個可以跨越多個數據中⼼的伺服器上作為集群運⾏。
  2. Kafka集群中按照主題分類管理,⼀個主題可以有多個分區,⼀個分區可以有多個副本分區。
  3. 每個記錄由⼀個鍵,⼀個值和⼀個時間戳組成。

Kafka 的 4 個核心 API

  1. Producer API:允許應⽤程式將記錄流發布到⼀個或多個Kafka主題。
  2. Consumer API:允許應⽤程式訂閱⼀個或多個主題並處理為其⽣成的記錄流。
  3. Streams API:允許應⽤程式充當串流處理器,使⽤⼀個或多個主題的輸⼊流,並⽣成⼀個或多個輸出主題的輸出流,從⽽有效地將輸⼊流轉換為輸出流。
  4. Connector API:允許構建和運⾏將Kafka主題連接到現有應⽤程式或數據系統的可重⽤⽣產者或使⽤者。例如,關係資料庫的連接器可能會捕獲對錶的所有更改。

二、Kafka 優勢

⾼吞吐量:單機每秒處理⼏⼗上百萬的消息量。即使存儲了許多TB的消息,它也保持穩定的性能。
⾼性能:單節點⽀持上千個客戶端,並保證零停機和零數據丟失。
持久化數據存儲:將消息持久化到磁碟。通過將數據持久化到硬碟以及replication防⽌數據丟失。

  • 零拷貝
  • 順序讀,順序寫
  • 利⽤Linux的⻚快取

分散式系統:易於向外擴展。所有的Producer、Broker和Consumer都會有多個,均為分散式的。⽆需停機即可擴展機器。多個Producer、Consumer可能是不同的應⽤。
可靠性:Kafka是分散式,分區,複製和容錯的。
客戶端狀態維護:消息被處理的狀態是在Consumer端維護,⽽不是由server端維護。當失敗時能⾃動平衡。
⽀持online和offline的場景
⽀持多種客戶端語⾔:Kafka⽀持Java、.NET、PHP、Python等多種語⾔。

三、Kafka 應用場景

⽇志收集:⼀個公司可以⽤Kafka可以收集各種服務的Log,通過Kafka以統⼀接⼝服務的⽅式開放給各種Consumer;
消息系統:解耦⽣產者和消費者、快取消息等;
⽤戶活動跟蹤:Kafka經常被⽤來記錄Web⽤戶或者App⽤戶的各種活動,如瀏覽⽹⻚、搜索、點擊等活動,這些活動資訊被各個伺服器發布到Kafka的Topic中,然後消費者通過訂閱這些Topic來做實時的監控分析,亦可保存到資料庫;
運營指標:Kafka也經常⽤來記錄運營監控數據。包括收集各種分散式應⽤的數據,⽣產各種操作的集中回饋,⽐如報警和報告;
流式處理:⽐如Spark Streaming和Storm。

四、Kafka 基本架構

消息和批次
消息:

  • Kafka 的數據單元稱為消息。消息可以看做資料庫表的一條「行記錄」,消息由位元組數組組成。
  • 消息有鍵,鍵也是一個位元組數組。當消息需要寫入不同的分區時,會使用鍵進行分區。

批次:

  • 消息可以分批寫入Kafka,一批次消息屬於同一個主題和分區。
  • 分批次寫入消息可以減少網路開銷。批次越大,單位時間處理消息越多,單個消息傳輸時間越長;批次消息數據會被壓縮,這樣能提升傳輸和存儲能力,也需要更多的計算處理。

模式

  • 消息模式(schema)有許多可⽤的選項,以便於理解。如JSON和XML,但是它們缺乏強類型處理能⼒
  • Kafka 使用的 Apache Avro(了解即可)。
  • 數據格式的⼀致性對Kafka很重要,因為它消除了消息讀寫操作之間的耦合性

主題和分區

  • Kafka的消息通過主題進⾏分類。主題可⽐是資料庫的表或者⽂件系統⾥的⽂件夾
  • 主題可以被分為若⼲分區,⼀個主題通過分區分布於Kafka集群中,提供了橫向擴展的能⼒

生產者和消費者
生產者:

  • ⽣產者創建消息。⼀個消息被發布到⼀個特定的主題上,⽣產者在默認情況下把消息均衡地分布到主題的所有分區上
    • 直接指定消息的分區
    • 根據消息的key散列取模得出分區
    • 輪詢指定分區

消費者:

  • 消費者消費消息。消費者通過偏移量來區分已經讀過的消息
  • 消費者是消費組的⼀部分。消費組保證每個分區只能被⼀個消費者使⽤,避免重複消費

broker和集群

  • 一個獨立的Kafka伺服器稱為broker。
  • broker接收來⾃⽣產者的消息,為消息設置偏移量,並提交消息到磁碟保存
  • broker為消費者提供服務,對讀取分區的請求做出響應,返回已經提交到磁碟上的消息
  • 單個broker可以輕鬆處理數千個分區以及每秒百萬級的消息量
  • 每個集群都有⼀個broker是集群控制器(⾃動從集群的活躍成員中選舉出來,通過Zookeeper的Master選舉)控制器負責管理⼯作
    • 將分區分配給broker
    • 監控broker
  • 集群中一個分區屬於一個 broker,該broker稱為分區首領
  • 一個分區可以分配給多個broker,此時會發生分區複製。分區複製提供了消息冗餘和高可用。副本分區不負責處理消息的讀寫

五、Kafka 核心概念

5.1 生產者 Producer

生產者創建消息,將消息發布到主題(Topic)中。一般一個消息會被發布到指定的主題上,然後通過以下幾種方式發布到指定主題分區:

  • 默認情況下通過輪詢把消息均衡地分布到主題的所有分區上
  • 有時我們可以將消息指定發到某一個分區上。通常是通過消息鍵和分區器來實現的,分區器可以為消息鍵計算出一個散列值,通過這個散列值就可以映射到相應的分區上
  • 也可以自定義分區器,我們可以根據不同的業務規則將消息映射到不同分區。

5.2 消費者 Consumer

消費者從主題中讀取消息

  • 消費者可以訂閱一個或多個主題,並按照消息生成的順序讀取
  • 消費者可以通過偏移量(Offset)區分已經讀取的消息
    • 偏移量是另⼀種元數據,它是⼀個不斷遞增的整數值,在創建消息時,Kafka 會把它添加到消息⾥
    • 在給定的分區⾥,每個消息的偏移量都是唯⼀的
    • 消費者把每個分區最後讀取的消息偏移量保存在Zookeeper 或Kafka(現在是存在Kafka上的) 上,如果消費者關閉或重啟,它的讀取狀態不會丟失
  • 消費者是消費組的一部分。消費組保證每個分區只能被一個消費者使用
  • 如果某一個消費者失效,就會進行再平衡,重新給消費組中的消費者分配消費分區,以達到高可用的目的

5.3 伺服器 Broker

一個獨立的Kafka伺服器就是一個 Broker。Broker為消費者提供服務,對讀取分區的請求做出響應,返回已經提交到磁碟上的消息。

  • 如果某topic有N個partition,集群有N個broker,那麼每個broker存儲該topic的⼀個partition
  • 如果某topic有N個partition,集群有(N+M)個broker,那麼其中有N個broker存儲該topic的⼀個partition,剩下的M個broker不存儲該topic的partition數據
  • 如果某topic有N個partition,集群中broker數⽬少於N個,那麼⼀個broker存儲該topic的⼀個或多個partition。在實際⽣產環境中,盡量避免這種情況的發⽣,這種情況容易導致Kafka集群數據不均衡

Broker 是集群的組成部分。每個集群都有⼀個broker 同時充當了集群控制器的⻆⾊(⾃動從集群的活躍成員中選舉出來):

  • 控制器負責管理⼯作,包括將分區分配給broker 和監控broker

在集群中,⼀個分區從屬於⼀個broker,該broker 被稱為分區的⾸領

5.4 主題 Topic

每條發布到Kafka的消息都有一個類別,這個類別就是Topic。

5.5 分區 Partition

主題可以分為若干個分區,消息可以寫主題的某一個分區中。
消息以追加的方式寫入分區,然後以先進後出的方式被讀取。
Kafka 無法在整個主題範圍內保證消息的順序,但是可以保證消息在單個分區中的順序。
Kafka 通過分區實現數據冗餘和伸縮性。
在需要嚴格保證消息順序的情況下,需要將分區設置為 1 。

5.6 副本 Replicas

5.6.1 副本概念

消息被寫入主題,每個主題有多個分區,每個分區有多個副本。副本被保存在broker 上,每個broker 可以保存成百上千個屬於不同主題和分區的副本
副本有兩種類型:

  • ⾸領副本:每個分區都有⼀個⾸領副本。為了保證⼀致性,所有⽣產者請求和消費者請求都會經過這個副本
  • 跟隨者副本:⾸領以外的副本都是跟隨者副本。跟隨者副本不處理來⾃客戶端的請求,它們唯⼀的任務就是從⾸領那⾥複製消息,保持與⾸領⼀致的狀態。如果⾸領發⽣崩潰,其中的⼀個跟隨者會被提升為新⾸領
5.6.1 副本介紹

Kafka 通過副本保證高可用。副本分為⾸領副本(Leader)和跟隨者副本(Follower)。
跟隨者副本包括同步副本和不同步副本,在發⽣⾸領副本切換的時候,只有同步副本可以切換為⾸領副本。

AR
分區中的所有副本統稱為AR(Assigned Repllicas)。AR=ISR+OSR

ISR

  • 所有與leader副本保持⼀定程度同步的副本(包括Leader)組成 ISR,ISR集合是AR集合中的⼀個⼦集。
  • 消息會先發送到leader副本,然後follower副本才能從leader副本中拉取消息進⾏同步,同步期間內follower副本相對於leader副本⽽⾔會有⼀定程度的滯後。前⾯所說的「⼀定程度」是指可以忍受的滯後範圍,這個範圍可以通過參數進⾏配置

OSR

  • 與leader副本同步滯後過多的副本(不包括Leader)組成 OSR。
  • 在正常情況下,所有的follower副本都應該與leader副本保持⼀定程度的同步,即AR=ISR,OSR集合為空

HW
HW是High Watermak的縮寫, 俗稱⾼⽔位,它表示了⼀個特定消息的偏移量(offset),消費之只能拉取到這個offset之前的消息。

LEO
LEO是Log End Offset的縮寫,它表示了當前⽇志⽂件中下⼀條待寫⼊消息的offset。

5.7 偏移量 Offset

5.7.1 生產者 Offset


消息寫⼊的時候,每⼀個分區都有⼀個offset,這個offset就是⽣產者的offset,同時也是這個分區的最新最⼤的offset
有些時候沒有指定某⼀個分區的offset,這個⼯作kafka幫我們完成

5.7.2 消費者 Offset


這是某⼀個分區的offset情況,⽣產者寫⼊的offset是最新最⼤的值是12,⽽當Consumer A進⾏消費時,從0開始消費,⼀直消費到了9,消費者的offset就記錄在9,Consumer B就紀錄在了11。等下⼀次他們再來消費時,他們可以選擇接著上⼀次的位置消費,當然也可以選擇從頭消費,或者跳到最近的記錄並從「現在」開始消費。