天天看點

從面試角度一文學完Kafka

Kafka 是一個優秀的分布式消息中間件,許多系統中都會使用到 Kafka 來做消息通信。對分布式消息系統的了解和使用幾乎成為一個背景開發人員必備的技能。今天

碼哥位元組

就從常見的 Kafka 面試題入手,和大家聊聊 Kafka 的那些事兒。

從面試角度一文學完Kafka

講一講分布式消息中間件

問題

  • 什麼是分布式消息中間件?
  • 消息中間件的作用是什麼?
  • 消息中間件的使用場景是什麼?
  • 消息中間件選型?
從面試角度一文學完Kafka

分布式消息是一種通信機制,和 RPC、HTTP、RMI 等不一樣,消息中間件采用分布式中間代理的方式進行通信。如圖所示,采用了消息中間件之後,上遊業務系統發送消息,先存儲在消息中間件,然後由消息中間件将消息分發到對應的業務子產品應用(分布式生産者 - 消費者模式)。這種異步的方式,減少了服務之間的耦合程度。

從面試角度一文學完Kafka

定義消息中間件:

  • 利用高效可靠的消息傳遞機制進行平台無關的資料交流
  • 基于資料通信,來進行分布式系統的內建
  • 通過提供消息傳遞和消息排隊模型,可以在分布式環境下擴充程序間的通信

在系統架構中引用額外的元件,必然提高系統的架構複雜度和運維的難度,那麼在系統中使用分布式消息中間件有什麼優勢呢?消息中間件在系統中起的作用又是什麼呢?

  • 解耦
  • 備援(存儲)
  • 擴充性
  • 削峰
  • 可恢複性
  • 順序保證
  • 緩沖
  • 異步通信

面試時,面試官經常會關心面試者對開源元件的選型能力,這既可以考驗面試者知識的廣度,也可以考驗面試者對某類系統的知識的認識深度,而且也可以看出面試者對系統整體把握和系統架構設計的能力。開源分布式消息系統有很多,不同的消息系統的特性也不一樣,選擇怎樣的消息系統,不僅需要對各消息系統有一定的了解,也需要對自身系統需求有清晰的認識。

下面是常見的幾種分布式消息系統的對比:

從面試角度一文學完Kafka

答案關鍵字

  • 什麼是分布式消息中間件?通信,隊列,分布式,生産消費者模式。
  • 消息中間件的作用是什麼? 解耦、峰值處理、異步通信、緩沖。
  • 消息中間件的使用場景是什麼? 異步通信,消息存儲處理。
  • 消息中間件選型?語言,協定、HA、資料可靠性、性能、事務、生态、簡易、推拉模式。

Kafka 基本概念和架構

問題

  • 簡單講下 Kafka 的架構?
  • Kafka 是推模式還是拉模式,推拉的差別是什麼?
  • Kafka 如何廣播消息?
  • Kafka 的消息是否是有序的?
  • Kafka 是否支援讀寫分離?
  • Kafka 如何保證資料高可用?
  • Kafka 中 zookeeper 的作用?
  • 是否支援事務?
  • 分區數是否可以減少?

Kafka 架構中的一般概念:

從面試角度一文學完Kafka
  • Producer:生産者,也就是發送消息的一方。生産者負責建立消息,然後将其發送到 Kafka。
  • Consumer:消費者,也就是接受消息的一方。消費者連接配接到 Kafka 上并接收消息,進而進行相應的業務邏輯處理。
  • Consumer Group:一個消費者組可以包含一個或多個消費者。使用多分區 + 多消費者方式可以極大提高資料下遊的處理速度,同一消費組中的消費者不會重複消費消息,同樣的,不同消費組中的消費者消息消息時互不影響。Kafka 就是通過消費組的方式來實作消息 P2P 模式和廣播模式。
  • Broker:服務代理節點。Broker 是 Kafka 的服務節點,即 Kafka 的伺服器。
  • Topic:Kafka 中的消息以 Topic 為機關進行劃分,生産者将消息發送到特定的 Topic,而消費者負責訂閱 Topic 的消息并進行消費。
  • Partition:Topic 是一個邏輯的概念,它可以細分為多個分區,每個分區隻屬于單個主題。同一個主題下不同分區包含的消息是不同的,分區在存儲層面可以看作一個可追加的日志(Log)檔案,消息在被追加到分區日志檔案的時候都會配置設定一個特定的偏移量(offset)。
  • Offset:offset 是消息在分區中的唯一辨別,Kafka 通過它來保證消息在分區内的順序性,不過 offset 并不跨越分區,也就是說,Kafka 保證的是分區有序性而不是主題有序性。
  • Replication:副本,是 Kafka 保證資料高可用的方式,Kafka 同一 Partition 的資料可以在多 Broker 上存在多個副本,通常隻有主副本對外提供讀寫服務,當主副本所在 broker 崩潰或發生網絡一場,Kafka 會在 Controller 的管理下會重新選擇新的 Leader 副本對外提供讀寫服務。
  • Record: 實際寫入 Kafka 中并可以被讀取的消息記錄。每個 record 包含了 key、value 和 timestamp。

Kafka Topic Partitions Layout

從面試角度一文學完Kafka

Kafka 将 Topic 進行分區,分區可以并發讀寫。

Kafka Consumer Offset

從面試角度一文學完Kafka

zookeeper

從面試角度一文學完Kafka
  • Broker 注冊:Broker 是分布式部署并且之間互相獨立,Zookeeper 用來管理注冊到叢集的所有 Broker 節點。
  • Topic 注冊: 在 Kafka 中,同一個 Topic 的消息會被分成多個分區并将其分布在多個 Broker 上,這些分區資訊及與 Broker 的對應關系也都是由 Zookeeper 在維護
  • 生産者負載均衡:由于同一個 Topic 消息會被分區并将其分布在多個 Broker 上,是以,生産者需要将消息合理地發送到這些分布式的 Broker 上。
  • 消費者負載均衡:與生産者類似,Kafka 中的消費者同樣需要進行負載均衡來實作多個消費者合理地從對應的 Broker 伺服器上接收消息,每個消費者分組包含若幹消費者,每條消息都隻會發送給分組中的一個消費者,不同的消費者分組消費自己特定的 Topic 下面的消息,互不幹擾。

答案關鍵字

  • 簡單講下 Kafka 的架構?
    Producer、Consumer、Consumer Group、Topic、Partition
  • Kafka 是推模式還是拉模式,推拉的差別是什麼?
    Kafka Producer 向 Broker 發送消息使用 Push 模式,Consumer 消費采用的 Pull 模式。拉取模式,讓 consumer 自己管理 offset,可以提供讀取性能
  • Kafka 如何廣播消息?
    Consumer group
  • Kafka 的消息是否是有序的?
    Topic 級别無序,Partition 有序
  • Kafka 是否支援讀寫分離?
    不支援,隻有 Leader 對外提供讀寫服務
  • Kafka 如何保證資料高可用?
    副本,ack,HW
  • Kafka 中 zookeeper 的作用?
    叢集管理,中繼資料管理
  • 是否支援事務?
    0.11 後支援事務,可以實作”exactly once“
  • 分區數是否可以減少?
    不可以,會丢失資料

Kafka 使用

問題

  • Kafka 有哪些指令行工具?你用過哪些?
  • Kafka Producer 的執行過程?
  • Kafka Producer 有哪些常見配置?
  • 如何讓 Kafka 的消息有序?
  • Producer 如何保證資料發送不丢失?
  • 如何提升 Producer 的性能?
  • 如果同一 group 下 consumer 的數量大于 part 的數量,kafka 如何處理?
  • Kafka Consumer 是否是線程安全的?
  • 講一下你使用 Kafka Consumer 消費消息時的線程模型,為何如此設計?
  • Kafka Consumer 的常見配置?
  • Consumer 什麼時候會被踢出叢集?
  • 當有 Consumer 加入或退出時,Kafka 會作何反應?
  • 什麼是 Rebalance,何時會發生 Rebalance?

指令行工具

Kafka 的指令行工具在 Kafka 包的

/bin

目錄下,主要包括服務和叢集管理腳本,配置腳本,資訊檢視腳本,Topic 腳本,用戶端腳本等。

  • kafka-configs.sh: 配置管理腳本
  • kafka-console-consumer.sh: kafka 消費者控制台
  • kafka-console-producer.sh: kafka 生産者控制台
  • kafka-consumer-groups.sh: kafka 消費者組相關資訊
  • kafka-delete-records.sh: 删除低水位的日志檔案
  • kafka-log-dirs.sh:kafka 消息日志目錄資訊
  • kafka-mirror-maker.sh: 不同資料中心 kafka 叢集複制工具
  • kafka-preferred-replica-election.sh: 觸發 preferred replica 選舉
  • kafka-producer-perf-test.sh:kafka 生産者性能測試腳本
  • kafka-reassign-partitions.sh: 分區重配置設定腳本
  • kafka-replica-verification.sh: 複制進度驗證腳本
  • kafka-server-start.sh: 啟動 kafka 服務
  • kafka-server-stop.sh: 停止 kafka 服務
  • kafka-topics.sh:topic 管理腳本
  • kafka-verifiable-consumer.sh: 可檢驗的 kafka 消費者
  • kafka-verifiable-producer.sh: 可檢驗的 kafka 生産者
  • zookeeper-server-start.sh: 啟動 zk 服務
  • zookeeper-server-stop.sh: 停止 zk 服務
  • zookeeper-shell.sh:zk 用戶端

我們通常可以使用

kafka-console-consumer.sh

kafka-console-producer.sh

腳本來測試 Kafka 生産和消費,

kafka-consumer-groups.sh

可以檢視和管理叢集中的 Topic,

kafka-topics.sh

通常用于檢視 Kafka 的消費組情況。

Kafka Producer

Kafka producer 的正常生産邏輯包含以下幾個步驟:

  1. 配置生産者用戶端參數常見生産者執行個體。
  2. 建構待發送的消息。
  3. 發送消息。
  4. 關閉生産者執行個體。

Producer 發送消息的過程如下圖所示,需要經過

攔截器

序列化器

分區器

,最終由

累加器

批量發送至 Broker。

從面試角度一文學完Kafka

Kafka Producer 需要以下必要參數:

  • bootstrap.server: 指定 Kafka 的 Broker 的位址
  • key.serializer: key 序列化器
  • value.serializer: value 序列化器

常見參數:

  • batch.num.messages
    預設值:200,每次批量消息的數量,隻對 asyc 起作用。
  • request.required.acks
    預設值:0,0 表示 producer 毋須等待 leader 的确認,1 代表需要 leader 确認寫入它的本地 log 并立即确認,-1 代表所有的備份都完成後确認。 隻對 async 模式起作用,這個參數的調整是資料不丢失和發送效率的 tradeoff,如果對資料丢失不敏感而在乎效率的場景可以考慮設定為 0,這樣可以大大提高 producer 發送資料的效率。
  • request.timeout.ms
    預設值:10000,确認逾時時間。
  • partitioner.class
    預設值:kafka.producer.DefaultPartitioner,必須實作 kafka.producer.Partitioner,根據 Key 提供一個分區政策。有時候我們需要相同類型的消息必須順序處理,這樣我們就必須自定義配置設定政策,進而将相同類型的資料配置設定到同一個分區中。
  • producer.type
    預設值:sync,指定消息發送是同步還是異步。異步 asyc 成批發送用 kafka.producer.AyncProducer, 同步 sync 用 kafka.producer.SyncProducer。同步和異步發送也會影響消息生産的效率。
  • compression.topic
    預設值:none,消息壓縮,預設不壓縮。其餘壓縮方式還有,"gzip"、"snappy"和"lz4"。對消息的壓縮可以極大地減少網絡傳輸量、降低網絡 IO,進而提高整體性能。
  • compressed.topics
    預設值:null,在設定了壓縮的情況下,可以指定特定的 topic 壓縮,未指定則全部壓縮。
  • message.send.max.retries
    預設值:3,消息發送最大嘗試次數。
  • retry.backoff.ms
    預設值:300,每次嘗試增加的額外的間隔時間。
  • topic.metadata.refresh.interval.ms
    預設值:600000,定期的擷取中繼資料的時間。當分區丢失,leader 不可用時 producer 也會主動擷取中繼資料,如果為 0,則每次發送完消息就擷取中繼資料,不推薦。如果為負值,則隻有在失敗的情況下擷取中繼資料。
  • queue.buffering.max.ms
    預設值:5000,在 producer queue 的緩存的資料最大時間,僅僅 for asyc。
  • queue.buffering.max.message
    預設值:10000,producer 緩存的消息的最大數量,僅僅 for asyc。
  • queue.enqueue.timeout.ms
    預設值:-1,0 當 queue 滿時丢掉,負值是 queue 滿時 block, 正值是 queue 滿時 block 相應的時間,僅僅 for asyc。

Kafka Consumer

Kafka 有消費組的概念,每個消費者隻能消費所配置設定到的分區的消息,每一個分區隻能被一個消費組中的一個消費者所消費,是以同一個消費組中消費者的數量如果超過了分區的數量,将會出現有些消費者配置設定不到消費的分區。消費組與消費者關系如下圖所示:

從面試角度一文學完Kafka

Kafka Consumer Client 消費消息通常包含以下步驟:

  1. 配置用戶端,建立消費者
  2. 訂閱主題
  3. 拉去消息并消費
  4. 送出消費位移
  5. 關閉消費者執行個體
從面試角度一文學完Kafka

因為 Kafka 的 Consumer 用戶端是線程不安全的,為了保證線程安全,并提升消費性能,可以在 Consumer 端采用類似 Reactor 的線程模型來消費資料。

從面試角度一文學完Kafka

Kafka consumer 參數

  • bootstrap.servers: 連接配接 broker 位址,

    host:port

    格式。
  • group.id: 消費者隸屬的消費組。
  • key.deserializer: 與生産者的

    key.serializer

    對應,key 的反序列化方式。
  • value.deserializer: 與生産者的

    value.serializer

    對應,value 的反序列化方式。
  • session.timeout.ms: coordinator 檢測失敗的時間。預設 10s 該參數是 Consumer Group 主動檢測 (組内成員 comsummer) 崩潰的時間間隔,類似于心跳過期時間。
  • auto.offset.reset: 該屬性指定了消費者在讀取一個沒有偏移量後者偏移量無效(消費者長時間失效目前的偏移量已經過時并且被删除了)的分區的情況下,應該作何處理,預設值是 latest,也就是從最新記錄讀取資料(消費者啟動之後生成的記錄),另一個值是 earliest,意思是在偏移量無效的情況下,消費者從起始位置開始讀取資料。
  • enable.auto.commit: 否自動送出位移,如果為

    false

    ,則需要在程式中手動送出位移。對于精确到一次的語義,最好手動送出位移
  • fetch.max.bytes: 單次拉取資料的最大位元組數量
  • max.poll.records: 單次 poll 調用傳回的最大消息數,如果處理邏輯很輕量,可以适當提高該值。 但是

    max.poll.records

    條資料需要在在 session.timeout.ms 這個時間内處理完 。預設值為 500
  • request.timeout.ms: 一次請求響應的最長等待時間。如果在逾時時間内未得到響應,kafka 要麼重發這條消息,要麼超過重試次數的情況下直接置為失敗。

Kafka Rebalance

rebalance 本質上是一種協定,規定了一個 consumer group 下的所有 consumer 如何達成一緻來配置設定訂閱 topic 的每個分區。比如某個 group 下有 20 個 consumer,它訂閱了一個具有 100 個分區的 topic。正常情況下,Kafka 平均會為每個 consumer 配置設定 5 個分區。這個配置設定的過程就叫 rebalance。

什麼時候 rebalance?

這也是經常被提及的一個問題。rebalance 的觸發條件有三種:

  • 組成員發生變更(新 consumer 加入組、已有 consumer 主動離開組或已有 consumer 崩潰了——這兩者的差別後面會談到)
  • 訂閱主題數發生變更
  • 訂閱主題的分區數發生變更

如何進行組内分區配置設定?

Kafka 預設提供了兩種配置設定政策:Range 和 Round-Robin。當然 Kafka 采用了可插拔式的配置設定政策,你可以建立自己的配置設定器以實作不同的配置設定政策。

答案關鍵字

  • Kafka 有哪些指令行工具?你用過哪些?

    /bin

    目錄,管理 kafka 叢集、管理 topic、生産和消費 kafka
  • Kafka Producer 的執行過程?攔截器,序列化器,分區器和累加器
  • Kafka Producer 有哪些常見配置?broker 配置,ack 配置,網絡和發送參數,壓縮參數,ack 參數
  • 如何讓 Kafka 的消息有序?Kafka 在 Topic 級别本身是無序的,隻有 partition 上才有序,是以為了保證處理順序,可以自定義分區器,将需順序處理的資料發送到同一個 partition
  • Producer 如何保證資料發送不丢失?ack 機制,重試機制
  • 如何提升 Producer 的性能?批量,異步,壓縮
  • 如果同一 group 下 consumer 的數量大于 part 的數量,kafka 如何處理?多餘的 Part 将處于無用狀态,不消費資料
  • Kafka Consumer 是否是線程安全的?不安全,單線程消費,多線程處理
  • 講一下你使用 Kafka Consumer 消費消息時的線程模型,為何如此設計?拉取和處理分離
  • Kafka Consumer 的常見配置?broker, 網絡和拉取參數,心跳參數
  • Consumer 什麼時候會被踢出叢集?奔潰,網絡異常,處理時間過長送出位移逾時
  • 當有 Consumer 加入或退出時,Kafka 會作何反應?進行 Rebalance
  • 什麼是 Rebalance,何時會發生 Rebalance?topic 變化,consumer 變化

高可用和性能

問題

  • Kafka 如何保證高可用?
  • Kafka 的傳遞語義?
  • Replic 的作用?
  • 什麼事 AR,ISR?
  • Leader 和 Flower 是什麼?
  • Kafka 中的 HW、LEO、LSO、LW 等分别代表什麼?
  • Kafka 為保證優越的性能做了哪些處理?

分區與副本

從面試角度一文學完Kafka

在分布式資料系統中,通常使用分區來提高系統的處理能力,通過副本來保證資料的高可用性。多分區意味着并發處理的能力,這多個副本中,隻有一個是 leader,而其他的都是 follower 副本。僅有 leader 副本可以對外提供服務。 多個 follower 副本通常存放在和 leader 副本不同的 broker 中。通過這樣的機制實作了高可用,當某台機器挂掉後,其他 follower 副本也能迅速”轉正“,開始對外提供服務。

為什麼 follower 副本不提供讀服務?

這個問題本質上是對性能和一緻性的取舍。試想一下,如果 follower 副本也對外提供服務那會怎麼樣呢?首先,性能是肯定會有所提升的。但同時,會出現一系列問題。類似資料庫事務中的幻讀,髒讀。 比如你現在寫入一條資料到 kafka 主題 a,消費者 b 從主題 a 消費資料,卻發現消費不到,因為消費者 b 去讀取的那個分區副本中,最新消息還沒寫入。而這個時候,另一個消費者 c 卻可以消費到最新那條資料,因為它消費了 leader 副本。Kafka 通過 WH 和 Offset 的管理來決定 Consumer 可以消費哪些資料,已經目前寫入的資料。

從面試角度一文學完Kafka

隻有 Leader 可以對外提供讀服務,那如何選舉 Leader

kafka 會将與 leader 副本保持同步的副本放到 ISR 副本集合中。當然,leader 副本是一直存在于 ISR 副本集合中的,在某些特殊情況下,ISR 副本中甚至隻有 leader 一個副本。 當 leader 挂掉時,kakfa 通過 zookeeper 感覺到這一情況,在 ISR 副本中選取新的副本成為 leader,對外提供服務。 但這樣還有一個問題,前面提到過,有可能 ISR 副本集合中,隻有 leader,當 leader 副本挂掉後,ISR 集合就為空,這時候怎麼辦呢?這時候如果設定 unclean.leader.election.enable 參數為 true,那麼 kafka 會在非同步,也就是不在 ISR 副本集合中的副本中,選取出副本成為 leader。

副本的存在就會出現副本同步問題

Kafka 在所有配置設定的副本 (AR) 中維護一個可用的副本清單 (ISR),Producer 向 Broker 發送消息時會根據

ack

配置來确定需要等待幾個副本已經同步了消息才相應成功,Broker 内部會

ReplicaManager

服務來管理 flower 與 leader 之間的資料同步。

從面試角度一文學完Kafka

性能優化

  • partition 并發
  • 順序讀寫磁盤
  • page cache:按頁讀寫
  • 預讀:Kafka 會将将要消費的消息提前讀入記憶體
  • 高性能序列化(二進制)
  • 記憶體映射
  • 無鎖 offset 管理:提高并發能力
  • Java NIO 模型
  • 批量:批量讀寫
  • 壓縮:消息壓縮,存儲壓縮,減小網絡和 IO 開銷

Partition 并發

一方面,由于不同 Partition 可位于不同機器,是以可以充分利用叢集優勢,實作機器間的并行處理。另一方面,由于 Partition 在實體上對應一個檔案夾,即使多個 Partition 位于同一個節點,也可通過配置讓同一節點上的不同 Partition 置于不同的 disk drive 上,進而實作磁盤間的并行處理,充分發揮多磁盤的優勢。

順序讀寫

Kafka 每一個 partition 目錄下的檔案被平均切割成大小相等(預設一個檔案是 500 兆,可以手動去設定)的資料檔案,

每一個資料檔案都被稱為一個段(segment file), 每個 segment 都采用 append 的方式追加資料。

從面試角度一文學完Kafka

答案關鍵字

  • Kafka 如何保證高可用?
    通過副本來保證資料的高可用,producer ack、重試、自動 Leader 選舉,Consumer 自平衡
  • Kafka 的傳遞語義?
    傳遞語義一般有

    at least once

    at most once

    exactly once

    。kafka 通過 ack 的配置來實作前兩種。
  • Replic 的作用?
    實作資料的高可用
  • 什麼是 AR,ISR?

    AR:Assigned Replicas。AR 是主題被建立後,分區建立時被配置設定的副本集合,副本個 數由副本因子決定。

    ISR:In-Sync Replicas。Kafka 中特别重要的概念,指代的是 AR 中那些與 Leader 保 持同步的副本集合。在 AR 中的副本可能不在 ISR 中,但 Leader 副本天然就包含在 ISR 中。關于 ISR,還有一個常見的面試題目是如何判斷副本是否應該屬于 ISR。目前的判斷 依據是:Follower 副本的 LEO 落後 Leader LEO 的時間,是否超過了 Broker 端參數 replica.lag.time.max.ms 值。如果超過了,副本就會被從 ISR 中移除。

  • Leader 和 Flower 是什麼?
  • Kafka 中的 HW 代表什麼?
    高水位值 (High watermark)。這是控制消費者可讀取消息範圍的重要字段。一 個普通消費者隻能“看到”Leader 副本上介于 Log Start Offset 和 HW(不含)之間的 所有消息。水位以上的消息是對消費者不可見的。
  • Kafka 為保證優越的性能做了哪些處理?

推薦閱讀

  • 資料庫系統設計概述
  • 不可不知的軟體架構模式
  • Tomcat 架構原了解析到架構設計借鑒
  • Tomcat 高并發之道原理拆解與性能調優