被問到 Kafka,不要再說你不會了

Kafka 是一個優秀的分佈式消息中間件,許多系統中都會使用到 Kafka 來作消息通訊。對分佈式消息系統的瞭解和使用幾乎成爲一個後臺開發人員必備的技能。今天碼哥字節就從常見的 Kafka 面試題入手,和你們聊聊 Kafka 的那些事兒。面試

思惟導圖

講一講分佈式消息中間件

問題

  • 什麼是分佈式消息中間件?
  • 消息中間件的做用是什麼?
  • 消息中間件的使用場景是什麼?
  • 消息中間件選型?

消息隊列

分佈式消息是一種通訊機制,和 RPC、HTTP、RMI 等不同,消息中間件採用分佈式中間代理的方式進行通訊。如圖所示,採用了消息中間件以後,上游業務系統發送消息,先存儲在消息中間件,而後由消息中間件將消息分發到對應的業務模塊應用(分佈式生產者 - 消費者模式)。這種異步的方式,減小了服務之間的耦合程度。shell

架構

定義消息中間件:數據庫

  • 利用高效可靠的消息傳遞機制進行平臺無關的數據交流
  • 基於數據通訊,來進行分佈式系統的集成
  • 經過提供消息傳遞和消息排隊模型,能夠在分佈式環境下擴展進程間的通訊

在系統架構中引用額外的組件,必然提升系統的架構複雜度和運維的難度,那麼在系統中使用分佈式消息中間件有什麼優點呢?消息中間件在系統中起的做用又是什麼呢?bootstrap

  • 解耦
  • 冗餘(存儲)
  • 擴展性
  • 削峯
  • 可恢復性
  • 順序保證
  • 緩衝
  • 異步通訊

面試時,面試官常常會關心面試者對開源組件的選型能力,這既能夠考驗面試者知識的廣度,也能夠考驗面試者對某類系統的知識的認識深度,並且也能夠看出面試者對系統總體把握和系統架構設計的能力。開源分佈式消息系統有不少,不一樣的消息系統的特性也不同,選擇怎樣的消息系統,不只須要對各消息系統有必定的瞭解,也須要對自身系統需求有清晰的認識。緩存

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

選擇

答案關鍵字

  • 什麼是分佈式消息中間件?通訊,隊列,分佈式,生產消費者模式。
  • 消息中間件的做用是什麼? 解耦、峯值處理、異步通訊、緩衝。
  • 消息中間件的使用場景是什麼? 異步通訊,消息存儲處理。
  • 消息中間件選型?語言,協議、HA、數據可靠性、性能、事務、生態、簡易、推拉模式。

Kafka 基本概念和架構

問題

  • 簡單講下 Kafka 的架構?
  • Kafka 是推模式仍是拉模式,推拉的區別是什麼?
  • Kafka 如何廣播消息?
  • Kafka 的消息是不是有序的?
  • Kafka 是否支持讀寫分離?
  • Kafka 如何保證數據高可用?
  • Kafka 中 zookeeper 的做用?
  • 是否支持事務?
  • 分區數是否能夠減小?

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 將 Topic 進行分區,分區能夠併發讀寫。網絡

Kafka Consumer Offsetsession

consumer offset

zookeeper

zookeeper

  • 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.shkafka-console-producer.sh腳原本測試 Kafka 生產和消費,kafka-consumer-groups.sh能夠查看和管理集羣中的 Topic,kafka-topics.sh一般用於查看 Kafka 的消費組狀況。

Kafka Producer

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

  1. 配置生產者客戶端參數常見生產者實例。
  2. 構建待發送的消息。
  3. 發送消息。
  4. 關閉生產者實例。

Producer 發送消息的過程以下圖所示,須要通過攔截器序列化器分區器,最終由累加器批量發送至 Broker。

producer

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 有消費組的概念,每一個消費者只能消費所分配到的分區的消息,每個分區只能被一個消費組中的一個消費者所消費,因此同一個消費組中消費者的數量若是超過了分區的數量,將會出現有些消費者分配不到消費的分區。消費組與消費者關係以下圖所示:

consumer group

Kafka Consumer Client 消費消息一般包含如下步驟:

  1. 配置客戶端,建立消費者
  2. 訂閱主題
  3. 拉去消息並消費
  4. 提交消費位移
  5. 關閉消費者實例

過程

由於 Kafka 的 Consumer 客戶端是線程不安全的,爲了保證線程安全,並提高消費性能,能夠在 Consumer 端採用相似 Reactor 的線程模型來消費數據。

消費模型

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 爲保證優越的性能作了哪些處理?

分區與副本

分區副本

在分佈式數據系統中,一般使用分區來提升系統的處理能力,經過副原本保證數據的高可用性。多分區意味着併發處理的能力,這多個副本中,只有一個是 leader,而其餘的都是 follower 副本。僅有 leader 副本能夠對外提供服務。 多個 follower 副本一般存放在和 leader 副本不一樣的 broker 中。經過這樣的機制實現了高可用,當某臺機器掛掉後,其餘 follower 副本也能迅速」轉正「,開始對外提供服務。

爲何 follower 副本不提供讀服務?

這個問題本質上是對性能和一致性的取捨。試想一下,若是 follower 副本也對外提供服務那會怎麼樣呢?首先,性能是確定會有所提高的。但同時,會出現一系列問題。相似數據庫事務中的幻讀,髒讀。 好比你如今寫入一條數據到 kafka 主題 a,消費者 b 從主題 a 消費數據,卻發現消費不到,由於消費者 b 去讀取的那個分區副本中,最新消息還沒寫入。而這個時候,另外一個消費者 c 卻能夠消費到最新那條數據,由於它消費了 leader 副本。Kafka 經過 WH 和 Offset 的管理來決定 Consumer 能夠消費哪些數據,已經當前寫入的數據。

watermark

只有 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 之間的數據同步。

sync

性能優化

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

Partition 併發

一方面,因爲不一樣 Partition 可位於不一樣機器,所以能夠充分利用集羣優點,實現機器間的並行處理。另外一方面,因爲 Partition 在物理上對應一個文件夾,即便多個 Partition 位於同一個節點,也可經過配置讓同一節點上的不一樣 Partition 置於不一樣的 disk drive 上,從而實現磁盤間的並行處理,充分發揮多磁盤的優點。

順序讀寫

Kafka 每個 partition 目錄下的文件被平均切割成大小相等(默認一個文件是 500 兆,能夠手動去設置)的數據文件,
每個數據文件都被稱爲一個段(segment file), 每一個 segment 都採用 append 的方式追加數據。

追加數據

答案關鍵字

  • Kafka 如何保證高可用?

    經過副原本保證數據的高可用,producer ack、重試、自動 Leader 選舉,Consumer 自平衡

  • Kafka 的交付語義?

    交付語義通常有at least onceat most onceexactly 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 爲保證優越的性能作了哪些處理?

    partition 併發、順序讀寫磁盤、page cache 壓縮、高性能序列化(二進制)、內存映射 無鎖 offset 管理、Java NIO 模型

本文並無深刻 Kafka 的實現細節和源碼分析,但 Kafka 確實是一個 優秀的開源系統,不少優雅的架構設計和源碼設計都值得咱們學習,十分建議感興趣的同窗更加深刻的去了解一下這個開源系統,對於自身架構設計能力,編碼能力,性能優化都會有很大的幫助。

推薦閱讀

如下幾篇文章閱讀量與讀者反饋都很好,推薦你們閱讀:

MageByte

相關文章
相關標籤/搜索