從面試角度一文學(xué)完 Kafka
Kafka 是一個優(yōu)秀的分布式消息中間件,許多系統(tǒng)中都會使用到 Kafka 來做消息通信。對分布式消息系統(tǒng)的了解和使用幾乎成為一個后臺開發(fā)人員必備的技能。今天就從常見的 Kafka 面試題入手,和大家聊聊 Kafka 的那些事兒。

講一講分布式消息中間件
問題
什么是分布式消息中間件?
消息中間件的作用是什么?
消息中間件的使用場景是什么?
消息中間件選型?

分布式消息是一種通信機制,和 RPC、HTTP、RMI 等不一樣,消息中間件采用分布式中間代理的方式進行通信。如圖所示,采用了消息中間件之后,上游業(yè)務(wù)系統(tǒng)發(fā)送消息,先存儲在消息中間件,然后由消息中間件將消息分發(fā)到對應(yīng)的業(yè)務(wù)模塊應(yīng)用(分布式生產(chǎn)者 - 消費者模式)。這種異步的方式,減少了服務(wù)之間的耦合程度。

定義消息中間件:
利用高效可靠的消息傳遞機制進行平臺無關(guān)的數(shù)據(jù)交流
基于數(shù)據(jù)通信,來進行分布式系統(tǒng)的集成
通過提供消息傳遞和消息排隊模型,可以在分布式環(huán)境下擴展進程間的通信
在系統(tǒng)架構(gòu)中引用額外的組件,必然提高系統(tǒng)的架構(gòu)復(fù)雜度和運維的難度,那么在系統(tǒng)中使用分布式消息中間件有什么優(yōu)勢呢?消息中間件在系統(tǒng)中起的作用又是什么呢?
解耦
冗余(存儲)
擴展性
削峰
可恢復(fù)性
順序保證
緩沖
異步通信
面試時,面試官經(jīng)常會關(guān)心面試者對開源組件的選型能力,這既可以考驗面試者知識的廣度,也可以考驗面試者對某類系統(tǒng)的知識的認識深度,而且也可以看出面試者對系統(tǒng)整體把握和系統(tǒng)架構(gòu)設(shè)計的能力。開源分布式消息系統(tǒng)有很多,不同的消息系統(tǒng)的特性也不一樣,選擇怎樣的消息系統(tǒng),不僅需要對各消息系統(tǒng)有一定的了解,也需要對自身系統(tǒng)需求有清晰的認識。
下面是常見的幾種分布式消息系統(tǒng)的對比:

答案關(guān)鍵字
什么是分布式消息中間件?通信,隊列,分布式,生產(chǎn)消費者模式。
消息中間件的作用是什么?解耦、峰值處理、異步通信、緩沖。
消息中間件的使用場景是什么?異步通信,消息存儲處理。
消息中間件選型?語言,協(xié)議、HA、數(shù)據(jù)可靠性、性能、事務(wù)、生態(tài)、簡易、推拉模式。
Kafka 基本概念和架構(gòu)
問題
簡單講下 Kafka 的架構(gòu)?
Kafka 是推模式還是拉模式,推拉的區(qū)別是什么?
Kafka 如何廣播消息?
Kafka 的消息是否是有序的?
Kafka 是否支持讀寫分離?
Kafka 如何保證數(shù)據(jù)高可用?
Kafka 中 zookeeper 的作用?
是否支持事務(wù)?
分區(qū)數(shù)是否可以減少?
Kafka 架構(gòu)中的一般概念:

Producer:生產(chǎn)者,也就是發(fā)送消息的一方。生產(chǎn)者負責創(chuàng)建消息,然后將其發(fā)送到 Kafka。
Consumer:消費者,也就是接受消息的一方。消費者連接到 Kafka 上并接收消息,進而進行相應(yīng)的業(yè)務(wù)邏輯處理。
Consumer Group:一個消費者組可以包含一個或多個消費者。使用多分區(qū) + 多消費者方式可以極大提高數(shù)據(jù)下游的處理速度,同一消費組中的消費者不會重復(fù)消費消息,同樣的,不同消費組中的消費者消息消息時互不影響。Kafka 就是通過消費組的方式來實現(xiàn)消息 P2P 模式和廣播模式。
Broker:服務(wù)代理節(jié)點。Broker 是 Kafka 的服務(wù)節(jié)點,即 Kafka 的服務(wù)器。
Topic:Kafka 中的消息以 Topic 為單位進行劃分,生產(chǎn)者將消息發(fā)送到特定的 Topic,而消費者負責訂閱 Topic 的消息并進行消費。
Partition:Topic 是一個邏輯的概念,它可以細分為多個分區(qū),每個分區(qū)只屬于單個主題。同一個主題下不同分區(qū)包含的消息是不同的,分區(qū)在存儲層面可以看作一個可追加的日志(Log)文件,消息在被追加到分區(qū)日志文件的時候都會分配一個特定的偏移量(offset)。
Offset:offset 是消息在分區(qū)中的唯一標識,Kafka 通過它來保證消息在分區(qū)內(nèi)的順序性,不過 offset 并不跨越分區(qū),也就是說,Kafka 保證的是分區(qū)有序性而不是主題有序性。
Replication:副本,是 Kafka 保證數(shù)據(jù)高可用的方式,Kafka 同一 Partition 的數(shù)據(jù)可以在多 Broker 上存在多個副本,通常只有主副本對外提供讀寫服務(wù),當主副本所在 broker 崩潰或發(fā)生網(wǎng)絡(luò)一場,Kafka 會在 Controller 的管理下會重新選擇新的 Leader 副本對外提供讀寫服務(wù)。
Record:實際寫入 Kafka 中并可以被讀取的消息記錄。每個 record 包含了 key、value 和 timestamp。
Kafka Topic Partitions Layout

Kafka 將 Topic 進行分區(qū),分區(qū)可以并發(fā)讀寫。
Kafka Consumer Offset

zookeeper

Broker 注冊:Broker 是分布式部署并且之間相互獨立,Zookeeper 用來管理注冊到集群的所有 Broker 節(jié)點。
Topic 注冊:在 Kafka 中,同一個 Topic 的消息會被分成多個分區(qū)并將其分布在多個 Broker 上,這些分區(qū)信息及與 Broker 的對應(yīng)關(guān)系也都是由 Zookeeper 在維護
生產(chǎn)者負載均衡:由于同一個 Topic 消息會被分區(qū)并將其分布在多個 Broker 上,因此,生產(chǎn)者需要將消息合理地發(fā)送到這些分布式的 Broker 上。
消費者負載均衡:與生產(chǎn)者類似,Kafka 中的消費者同樣需要進行負載均衡來實現(xiàn)多個消費者合理地從對應(yīng)的 Broker 服務(wù)器上接收消息,每個消費者分組包含若干消費者,每條消息都只會發(fā)送給分組中的一個消費者,不同的消費者分組消費自己特定的 Topic 下面的消息,互不干擾。
答案關(guān)鍵字
簡單講下 Kafka 的架構(gòu)? Producer、Consumer、Consumer Group、Topic、Partition Kafka 是推模式還是拉模式,推拉的區(qū)別是什么? Kafka Producer 向 Broker 發(fā)送消息使用 Push 模式,Consumer 消費采用的 Pull 模式。拉取模式,讓 consumer 自己管理 offset,可以提供讀取性能 Kafka 如何廣播消息? Consumer group Kafka 的消息是否是有序的? Topic 級別無序,Partition 有序 Kafka 是否支持讀寫分離? 不支持,只有 Leader 對外提供讀寫服務(wù) Kafka 如何保證數(shù)據(jù)高可用? 副本,ack,HW Kafka 中 zookeeper 的作用? 集群管理,元數(shù)據(jù)管理 是否支持事務(wù)? 0.11 后支持事務(wù),可以實現(xiàn)”exactly once“ 分區(qū)數(shù)是否可以減少? 不可以,會丟失數(shù)據(jù)
Kafka 使用
問題
Kafka 有哪些命令行工具?你用過哪些? Kafka Producer 的執(zhí)行過程? Kafka Producer 有哪些常見配置? 如何讓 Kafka 的消息有序? Producer 如何保證數(shù)據(jù)發(fā)送不丟失? 如何提升 Producer 的性能? 如果同一 group 下 consumer 的數(shù)量大于 part 的數(shù)量,kafka 如何處理? Kafka Consumer 是否是線程安全的? 講一下你使用 Kafka Consumer 消費消息時的線程模型,為何如此設(shè)計? Kafka Consumer 的常見配置? Consumer 什么時候會被踢出集群? 當有 Consumer 加入或退出時,Kafka 會作何反應(yīng)? 什么是 Rebalance,何時會發(fā)生 Rebalance?
命令行工具
/bin目錄下,主要包括服務(wù)和集群管理腳本,配置腳本,信息查看腳本,Topic 腳本,客戶端腳本等。kafka-configs.sh:配置管理腳本 kafka-console-consumer.sh:kafka 消費者控制臺 kafka-console-producer.sh:kafka 生產(chǎn)者控制臺 kafka-consumer-groups.sh:kafka 消費者組相關(guān)信息 kafka-delete-records.sh:刪除低水位的日志文件 kafka-log-dirs.sh:kafka 消息日志目錄信息 kafka-mirror-maker.sh:不同數(shù)據(jù)中心 kafka 集群復(fù)制工具 kafka-preferred-replica-election.sh:觸發(fā) preferred replica 選舉 kafka-producer-perf-test.sh:kafka 生產(chǎn)者性能測試腳本 kafka-reassign-partitions.sh:分區(qū)重分配腳本 kafka-replica-verification.sh:復(fù)制進度驗證腳本 kafka-server-start.sh:啟動 kafka 服務(wù) kafka-server-stop.sh:停止 kafka 服務(wù) kafka-topics.sh:topic 管理腳本 kafka-verifiable-consumer.sh:可檢驗的 kafka 消費者 kafka-verifiable-producer.sh:可檢驗的 kafka 生產(chǎn)者 zookeeper-server-start.sh:啟動 zk 服務(wù) zookeeper-server-stop.sh:停止 zk 服務(wù) zookeeper-shell.sh:zk 客戶端
kafka-console-consumer.sh和kafka-console-producer.sh腳本來測試 Kafka 生產(chǎn)和消費,kafka-consumer-groups.sh可以查看和管理集群中的 Topic,kafka-topics.sh通常用于查看 Kafka 的消費組情況。Kafka Producer
配置生產(chǎn)者客戶端參數(shù)常見生產(chǎn)者實例。 構(gòu)建待發(fā)送的消息。 發(fā)送消息。 關(guān)閉生產(chǎn)者實例。
攔截器,序列化器和分區(qū)器,最終由累加器批量發(fā)送至 Broker。
bootstrap.server:指定 Kafka 的 Broker 的地址 key.serializer:key 序列化器 value.serializer:value 序列化器
batch.num.messages 默認值:200,每次批量消息的數(shù)量,只對 asyc 起作用。 request.required.acks 默認值:0,0 表示 producer 毋須等待 leader 的確認,1 代表需要 leader 確認寫入它的本地 log 并立即確認,-1 代表所有的備份都完成后確認。只對 async 模式起作用,這個參數(shù)的調(diào)整是數(shù)據(jù)不丟失和發(fā)送效率的 tradeoff,如果對數(shù)據(jù)丟失不敏感而在乎效率的場景可以考慮設(shè)置為 0,這樣可以大大提高 producer 發(fā)送數(shù)據(jù)的效率。 request.timeout.ms 默認值:10000,確認超時時間。 partitioner.class 默認值:kafka.producer.DefaultPartitioner,必須實現(xiàn) kafka.producer.Partitioner,根據(jù) Key 提供一個分區(qū)策略。有時候我們需要相同類型的消息必須順序處理,這樣我們就必須自定義分配策略,從而將相同類型的數(shù)據(jù)分配到同一個分區(qū)中。 producer.type 默認值:sync,指定消息發(fā)送是同步還是異步。異步 asyc 成批發(fā)送用 kafka.producer.AyncProducer, 同步 sync 用 kafka.producer.SyncProducer。同步和異步發(fā)送也會影響消息生產(chǎn)的效率。 compression.topic 默認值:none,消息壓縮,默認不壓縮。其余壓縮方式還有,"gzip"、"snappy"和"lz4"。對消息的壓縮可以極大地減少網(wǎng)絡(luò)傳輸量、降低網(wǎng)絡(luò) IO,從而提高整體性能。 compressed.topics 默認值:null,在設(shè)置了壓縮的情況下,可以指定特定的 topic 壓縮,未指定則全部壓縮。 message.send.max.retries 默認值:3,消息發(fā)送最大嘗試次數(shù)。 retry.backoff.ms 默認值:300,每次嘗試增加的額外的間隔時間。 topic.metadata.refresh.interval.ms 默認值:600000,定期的獲取元數(shù)據(jù)的時間。當分區(qū)丟失,leader 不可用時 producer 也會主動獲取元數(shù)據(jù),如果為 0,則每次發(fā)送完消息就獲取元數(shù)據(jù),不推薦。如果為負值,則只有在失敗的情況下獲取元數(shù)據(jù)。 queue.buffering.max.ms 默認值:5000,在 producer queue 的緩存的數(shù)據(jù)最大時間,僅僅 for asyc。 queue.buffering.max.message 默認值:10000,producer 緩存的消息的最大數(shù)量,僅僅 for asyc。 queue.enqueue.timeout.ms 默認值:-1,0 當 queue 滿時丟掉,負值是 queue 滿時 block, 正值是 queue 滿時 block 相應(yīng)的時間,僅僅 for asyc。
Kafka Consumer

配置客戶端,創(chuàng)建消費者 訂閱主題 拉去消息并消費 提交消費位移 關(guān)閉消費者實例


Kafka consumer 參數(shù)
bootstrap.servers:連接 broker 地址, host:port格式。group.id:消費者隸屬的消費組。 key.deserializer:與生產(chǎn)者的 key.serializer對應(yīng),key 的反序列化方式。value.deserializer:與生產(chǎn)者的 value.serializer對應(yīng),value 的反序列化方式。session.timeout.ms:coordinator 檢測失敗的時間。默認 10s 該參數(shù)是 Consumer Group 主動檢測 (組內(nèi)成員 comsummer) 崩潰的時間間隔,類似于心跳過期時間。 auto.offset.reset:該屬性指定了消費者在讀取一個沒有偏移量后者偏移量無效(消費者長時間失效當前的偏移量已經(jīng)過時并且被刪除了)的分區(qū)的情況下,應(yīng)該作何處理,默認值是 latest,也就是從最新記錄讀取數(shù)據(jù)(消費者啟動之后生成的記錄),另一個值是 earliest,意思是在偏移量無效的情況下,消費者從起始位置開始讀取數(shù)據(jù)。 enable.auto.commit:否自動提交位移,如果為 false,則需要在程序中手動提交位移。對于精確到一次的語義,最好手動提交位移fetch.max.bytes:單次拉取數(shù)據(jù)的最大字節(jié)數(shù)量 max.poll.records:單次 poll 調(diào)用返回的最大消息數(shù),如果處理邏輯很輕量,可以適當提高該值。但是 max.poll.records條數(shù)據(jù)需要在在 session.timeout.ms 這個時間內(nèi)處理完 。默認值為 500request.timeout.ms:一次請求響應(yīng)的最長等待時間。如果在超時時間內(nèi)未得到響應(yīng),kafka 要么重發(fā)這條消息,要么超過重試次數(shù)的情況下直接置為失敗。
Kafka Rebalance
組成員發(fā)生變更(新 consumer 加入組、已有 consumer 主動離開組或已有 consumer 崩潰了——這兩者的區(qū)別后面會談到) 訂閱主題數(shù)發(fā)生變更 訂閱主題的分區(qū)數(shù)發(fā)生變更
答案關(guān)鍵字
Kafka 有哪些命令行工具?你用過哪些? /bin目錄,管理 kafka 集群、管理 topic、生產(chǎn)和消費 kafkaKafka Producer 的執(zhí)行過程?攔截器,序列化器,分區(qū)器和累加器 Kafka Producer 有哪些常見配置?broker 配置,ack 配置,網(wǎng)絡(luò)和發(fā)送參數(shù),壓縮參數(shù),ack 參數(shù) 如何讓 Kafka 的消息有序?Kafka 在 Topic 級別本身是無序的,只有 partition 上才有序,所以為了保證處理順序,可以自定義分區(qū)器,將需順序處理的數(shù)據(jù)發(fā)送到同一個 partition Producer 如何保證數(shù)據(jù)發(fā)送不丟失?ack 機制,重試機制 如何提升 Producer 的性能?批量,異步,壓縮 如果同一 group 下 consumer 的數(shù)量大于 part 的數(shù)量,kafka 如何處理?多余的 Part 將處于無用狀態(tài),不消費數(shù)據(jù) Kafka Consumer 是否是線程安全的?不安全,單線程消費,多線程處理 講一下你使用 Kafka Consumer 消費消息時的線程模型,為何如此設(shè)計?拉取和處理分離 Kafka Consumer 的常見配置?broker, 網(wǎng)絡(luò)和拉取參數(shù),心跳參數(shù) Consumer 什么時候會被踢出集群?奔潰,網(wǎng)絡(luò)異常,處理時間過長提交位移超時 當有 Consumer 加入或退出時,Kafka 會作何反應(yīng)?進行 Rebalance 什么是 Rebalance,何時會發(fā)生 Rebalance?topic 變化,consumer 變化
高可用和性能
問題
Kafka 如何保證高可用? Kafka 的交付語義? Replic 的作用? 什么事 AR,ISR? Leader 和 Flower 是什么? Kafka 中的 HW、LEO、LSO、LW 等分別代表什么? Kafka 為保證優(yōu)越的性能做了哪些處理?
分區(qū)與副本


ack配置來確定需要等待幾個副本已經(jīng)同步了消息才相應(yīng)成功,Broker 內(nèi)部會ReplicaManager服務(wù)來管理 flower 與 leader 之間的數(shù)據(jù)同步。
性能優(yōu)化
partition 并發(fā) 順序讀寫磁盤 page cache:按頁讀寫 預(yù)讀:Kafka 會將將要消費的消息提前讀入內(nèi)存 高性能序列化(二進制) 內(nèi)存映射 無鎖 offset 管理:提高并發(fā)能力 Java NIO 模型 批量:批量讀寫 壓縮:消息壓縮,存儲壓縮,減小網(wǎng)絡(luò)和 IO 開銷
Partition 并發(fā)
順序讀寫

答案關(guān)鍵字
Kafka 如何保證高可用? 通過副本來保證數(shù)據(jù)的高可用,producer ack、重試、自動 Leader 選舉,Consumer 自平衡 Kafka 的交付語義? 交付語義一般有 at least once、at most once和exactly once。kafka 通過 ack 的配置來實現(xiàn)前兩種。Replic 的作用? 實現(xiàn)數(shù)據(jù)的高可用 什么是 AR,ISR? AR:Assigned Replicas。AR 是主題被創(chuàng)建后,分區(qū)創(chuàng)建時被分配的副本集合,副本個 數(shù)由副本因子決定。ISR:In-Sync Replicas。Kafka 中特別重要的概念,指代的是 AR 中那些與 Leader 保 持同步的副本集合。在 AR 中的副本可能不在 ISR 中,但 Leader 副本天然就包含在 ISR 中。關(guān)于 ISR,還有一個常見的面試題目是如何判斷副本是否應(yīng)該屬于 ISR。目前的判斷 依據(jù)是:Follower 副本的 LEO 落后 Leader LEO 的時間,是否超過了 Broker 端參數(shù) replica.lag.time.max.ms 值。如果超過了,副本就會被從 ISR 中移除。 Leader 和 Flower 是什么? Kafka 中的 HW 代表什么? 高水位值 (High watermark)。這是控制消費者可讀取消息范圍的重要字段。一 個普通消費者只能“看到”Leader 副本上介于 Log Start Offset 和 HW(不含)之間的 所有消息。水位以上的消息是對消費者不可見的。 Kafka 為保證優(yōu)越的性能做了哪些處理? partition 并發(fā)、順序讀寫磁盤、page cache 壓縮、高性能序列化(二進制)、內(nèi)存映射 無鎖 offset 管理、Java NIO 模型
有道無術(shù),術(shù)可成;有術(shù)無道,止于術(shù)
歡迎大家關(guān)注Java之道公眾號
好文章,我在看??
