天天看點

【Java面試系列】kafka面試題熱門系列:目錄1.kafka 面試題2.題目解析 

熱門系列:

  • 【Java面試系列】2020年最新最全java面試題大全及答案解析

  • 【消息中間件MQ系列】消息隊列ActiveMQ、RocketMQ、RabbitMQ、Kafka不得不說的秘密

  • 【ELK架構系列】SpringBoot+Kafka+ELK內建日志采集可視化架構

  • 【ELK架構系列】Logstash結合Kafka,根據不同Topic建立ES區分索引

  •   程式人生,精彩搶先看

目錄

1.kafka 面試題

2.題目解析

    1、如何擷取 topic 主題的清單

    2、生産者和消費者的指令行是什麼?

    3、consumer 是推還是拉?

    4、講講 kafka 維護消費狀态跟蹤的方法

    5、講一下主從同步

    6、為什麼需要消息系統,mysql 不能滿足需求嗎?

    7、Zookeeper 對于 Kafka 的作用是什麼?

    9、Kafka 判斷一個節點是否還活着有那兩個條件?

    10、Kafka 與傳統 MQ 消息系統之間有三個關鍵差別

    11、講一講 kafka 的 ack 的三種機制

    12、消費者如何不自動送出偏移量,由應用送出?

    13、消費者故障,出現活鎖問題如何解決?

    14、如何控制消費的位置

    15、kafka 分布式(不是單機)的情況下,如何保證消息的順序消費?

    16、kafka 的高可用機制是什麼?

    17、kafka 如何減少資料丢失

    18、kafka 如何不消費重複資料?比如扣款,我們不能重複的扣。

1.kafka 面試題

1、如何擷取 topic 主題的清單

2、生産者和消費者的指令行是什麼?

3、consumer 是推還是拉?

4、講講 kafka 維護消費狀态跟蹤的方法

5、講一下主從同步

6、為什麼需要消息系統,mysql 不能滿足需求嗎?

7、Zookeeper 對于 Kafka 的作用是什麼?

8、資料傳輸的事務定義有哪三種?

9、Kafka 判斷一個節點是否還活着有那兩個條件?

10、Kafka 與傳統 MQ 消息系統之間有三個關鍵差別

11、講一講 kafka 的 ack 的三種機制

12、消費者如何不自動送出偏移量,由應用送出?

13、消費者故障,出現活鎖問題如何解決?

14、如何控制消費的位置

15、kafka 分布式(不是單機)的情況下,如何保證消息的順序消費?

16、kafka 的高可用機制是什麼?

17、kafka 如何減少資料丢失

18、kafka 如何不消費重複資料?比如扣款,我們不能重複的扣。

2.題目解析

1、如何擷取 topic 主題的清單

bin/kafka-topics.sh --list --zookeeper localhost:2181

2、生産者和消費者的指令行是什麼?

生産者在主題上釋出消息:

bin/kafka-console-producer.sh --broker-list 192.168.43.49:9092 --topicHello-Kafka

注意這裡的 IP 是 server.properties 中的 listeners 的配置。接下來每個新行就是輸入一條新消息。

消費者接受消息:

bin/kafka-console-consumer.sh --zookeeper localhost:2181 --topicHello-Kafka --from-beginning

3、consumer 是推還是拉?

Kafka 最初考慮的問題是,customer 應該從 brokes 拉取消息還是 brokers 将消息推送到 consumer,也就是 pull 還 push。在這方面,Kafka 遵循了一種大部分消息系統共同的傳統的設計:producer 将消息推送到 broker,consumer 從broker 拉取消息。

一些消息系統比如 Scribe 和 Apache Flume 采用了 push 模式,将消息推送到下遊的 consumer。這樣做有好處也有壞處:由 broker 決定消息推送的速率,對于不同消費速率的 consumer 就不太好處理了。消息系統都緻力于讓 consumer 以最大的速率最快速的消費消息,但不幸的是,push 模式下,當 broker 推送的速率遠大于 consumer 消費的速率時,consumer 恐怕就要崩潰了。最終 Kafka 還是選取了傳統的 pull 模式。

Pull 模式的另外一個好處是 consumer 可以自主決定是否批量的從 broker 拉取資料 。Push 模式必須在不知道下遊 consumer 消費能力和消費政策的情況下決定是立即推送每條消息還是緩存之後批量推送。如果為了避免 consumer 崩潰而采用較低的推送速率,将可能導緻一次隻推送較少的消息而造成浪費。Pull 模式下,consumer 就可以根據自己的消費能力去決定這些政策。

Pull 有個缺點是,如果 broker 沒有可供消費的消息,将導緻 consumer 不斷在循環中輪詢,直到新消息到 t 達。為了避免這點,Kafka 有個參數可以讓 consumer阻塞知道新消息到達(當然也可以阻塞知道消息的數量達到某個特定的量這樣就可以批量發送)。

4、講講 kafka 維護消費狀态跟蹤的方法

大部分消息系統在 broker 端的維護消息被消費的記錄:一個消息被分發到consumer 後 broker 就馬上進行标記或者等待 customer 的通知後進行标記。這樣也可以在消息在消費後立馬就删除以減少空間占用。

但是這樣會不會有什麼問題呢?如果一條消息發送出去之後就立即被标記為消費過的,旦 consumer 處理消息時失敗了(比如程式崩潰)消息就丢失了。為了解決這個問題,很多消息系統提供了另外一個個功能:當消息被發送出去之後僅僅被标記為已發送狀态,當接到 consumer 已經消費成功的通知後才标記為已被消費的狀态。這雖然解決了消息丢失的問題,但産生了新問題,首先如果 consumer處理消息成功了但是向 broker 發送響應時失敗了,這條消息将被消費兩次。第二個問題時,broker 必須維護每條消息的狀态,并且每次都要先鎖住消息然後更改狀态然後釋放鎖。這樣麻煩又來了,且不說要維護大量的狀态資料,比如如果消息發送出去但沒有收到消費成功的通知,這條消息将一直處于被鎖定的狀态,Kafka 采用了不同的政策。Topic 被分成了若幹分區,每個分區在同一時間隻被一個 consumer 消費。這意味着每個分區被消費的消息在日志中的位置僅僅是一個簡單的整數:offset。這樣就很容易标記每個分區消費狀态就很容易了,僅僅需要一個整數而已。這樣消費狀态的跟蹤就很簡單了。

這帶來了另外一個好處:consumer 可以把 offset 調成一個較老的值,去重新消費老的消息。這對傳統的消息系統來說看起來有些不可思議,但确實是非常有用的,誰規定了一條消息隻能被消費一次呢?

5、講一下主從同步

Kafka允許topic的分區擁有若幹副本,這個數量是可以配置的,你可以為每個topci配置副本的數量。Kafka會自動在每個個副本上備份資料,是以當一個節點down掉時資料依然是可用的。

Kafka的副本功能不是必須的,你可以配置隻有一個副本,這樣其實就相當于隻有一份資料。

6、為什麼需要消息系統,mysql 不能滿足需求嗎?

(1)解耦:

允許你獨立的擴充或修改兩邊的處理過程,隻要確定它們遵守同樣的接口限制。

(2)備援:

消息隊列把資料進行持久化直到它們已經被完全處理,通過這一方式規避了資料丢失風險。許多消息隊列所采用的”插入-擷取-删除”範式中,在把一個消息從隊列中删除之前,需要你的處理系統明确的指出該消息已經被處理完畢,進而確定你的資料被安全的儲存直到你使用完畢。

(3)擴充性:

因為消息隊列解耦了你的處理過程,是以增大消息入隊和處理的頻率是很容易的,隻要另外增加處理過程即可。

(4)靈活性 & 峰值處理能力:

在通路量劇增的情況下,應用仍然需要繼續發揮作用,但是這樣的突發流量并不常見。如果為以能處理這類峰值通路為标準來投入資源随時待命無疑是巨大的浪費。使用消息隊列能夠使關鍵元件頂住突發的通路壓力,而不會因為突發的超負荷的請求而完全崩潰。

(5)可恢複性:

系統的一部分元件失效時,不會影響到整個系統。消息隊列降低了程序間的耦合度,是以即使一個處理消息的程序挂掉,加入隊列中的消息仍然可以在系統恢複後被處理。

(6)順序保證:

在大多使用場景下,資料處理的順序都很重要。大部分消息隊列本來就是排序的,并且能保證資料會按照特定的順序來處理。(Kafka 保證一個 Partition 内的消息的有序性)

(7)緩沖:

有助于控制和優化資料流經過系統的速度,解決生産消息和消費消息的處理速度不一緻的情況。

(8)異步通信:

很多時候,使用者不想也不需要立即處理消息。消息隊列提供了異步處理機制,允許使用者把一個消息放入隊列,但并不立即處理它。想向隊列中放入多少消息就放多少,然後在需要的時候再去處理它們。

7、Zookeeper 對于 Kafka 的作用是什麼?

Zookeeper 是一個開放源碼的、高性能的協調服務,它用于 Kafka 的分布式應用。

Zookeeper 主要用于在叢集中不同節點之間進行通信

在 Kafka 中,它被用于送出偏移量,是以如果節點在任何情況下都失敗了,它都可以從之前送出的偏移量中擷取除此之外,它還執行其他活動,如: leader 檢測、分布式同步、配置管理、識别新節點何時離開或連接配接、叢集、節點實時狀态等等。

8、資料傳輸的事務定義有哪三種?

和 MQTT 的事務定義一樣都是 3 種。

(1)最多一次: 消息不會被重複發送,最多被傳輸一次,但也有可能一次不傳輸

(2)最少一次: 消息不會被漏發送,最少被傳輸一次,但也有可能被重複傳輸.

(3)精确的一次(Exactly once): 不會漏傳輸也不會重複傳輸,每個消息都傳輸被一次而且僅僅被傳輸一次,這是大家所期望的

9、Kafka 判斷一個節點是否還活着有那兩個條件?

(1)節點必須可以維護和 ZooKeeper 的連接配接,Zookeeper 通過心跳機制檢查每個節點的連接配接

(2)如果節點是個 follower,他必須能及時的同步 leader 的寫操作,延時不能太久

10、Kafka 與傳統 MQ 消息系統之間有三個關鍵差別

(1).Kafka 持久化日志,這些日志可以被重複讀取和無限期保留

(2).Kafka 是一個分布式系統:它以叢集的方式運作,可以靈活伸縮,在内部通過複制資料提升容錯能力和高可用性

(3).Kafka 支援實時的流式處理

11、講一講 kafka 的 ack 的三種機制

request.required.acks 有三個值 0 1 -1(all)

0:生産者不會等待 broker 的 ack,這個延遲最低但是存儲的保證最弱當 server 挂掉的時候就會丢資料。(持久性最差,延時性最好)

1:服務端會等待 ack 值 leader 副本确認接收到消息後發送 ack 但是如果 leader挂掉後他不確定是否複制完成新 leader 也會導緻資料丢失。(持久性較好,延時性也較好)

-1(all):服務端在isr集合裡面的leader收到消息之後,并且isr的其餘follower複制成功之後才會發送ack給producer。(持久性最好,延時性最差)

12、消費者如何不自動送出偏移量,由應用送出?

将 auto.commit.offset 設為 false,然後在處理一批消息後 commitSync() 或者異步送出 commitAsync()

即:

ConsumerRecords<> records = consumer.poll();
for (ConsumerRecord<> record : records){
	
	tyr{
		consumer.commitSync()
	}
	
}
           

13、消費者故障,出現活鎖問題如何解決?

出現“活鎖”的情況,是它持續的發送心跳,但是沒有處理。為了預防消費者在這種情況下一直持有分區,我們使用 max.poll.interval.ms 活躍檢測機制。 在此基礎上,如果你調用的 poll 的頻率大于最大間隔,則用戶端将主動地離開組,以便其他消費者接管該分區。 發生這種情況時,你會看到 offset 送出失敗(調用commitSync()引發的 CommitFailedException)。這是一種安全機制,保障隻有活動成員能夠送出 offset。是以要留在組中,你必須持續調用 poll。

消費者提供兩個配置設定來控制 poll 循環:

max.poll.interval.ms:增大 poll 的間隔,可以為消費者提供更多的時間去處理傳回的消息(調用 poll(long)傳回的消息,通常傳回的消息都是一批)。缺點是此值越大将會延遲組重新平衡。

max.poll.records:此設定限制每次調用 poll 傳回的消息數,這樣可以更容易的預測每次 poll 間隔要處理的最大值。通過調整此值,可以減少 poll 間隔,減少重新平衡分組的

對于消息處理時間不可預測地的情況,這些選項是不夠的。 處理這種情況的推薦方法是将消息處理移到另一個線程中,讓消費者繼續調用 poll。 但是必須注意確定已送出的 offset 不超過實際位置。另外,你必須禁用自動送出,并隻有線上程完成處理後才為記錄手動送出偏移量(取決于你)。 還要注意,你需要 pause 暫停分區,不會從 poll 接收到新消息,讓線程處理完之前傳回的消息(如果你的處理能力比拉取消息的慢,那建立新線程将導緻你機器記憶體溢出)。

14、如何控制消費的位置

kafka 使用 seek(TopicPartition, long)指定新的消費位置。用于查找伺服器保留的最早和最新的 offset 的特殊的方法也可用(seekToBeginning(Collection) 和seekToEnd(Collection))

15、kafka 分布式(不是單機)的情況下,如何保證消息的順序消費?

Kafka 分布式的機關是 partition,同一個 partition 用一個 write ahead log 組織,是以可以保證 FIFO 的順序。不同 partition 之間不能保證順序。但是絕大多數使用者都可以通過 message key 來定義,因為同一個 key 的 message 可以保證隻發送到同一個 partition。

Kafka 中發送 1 條消息的時候,可以指定(topic, partition, key) 3 個參數。partiton 和 key 是可選的。如果你指定了 partition,那就是所有消息發往同 1個 partition,就是有序的。并且在消費端,Kafka 保證,1 個 partition 隻能被1 個 consumer 消費。或者你指定 key( 比如 order id),具有同 1 個 key 的所有消息,會發往同 1 個 partition。

16、kafka 的高可用機制是什麼?

這個問題比較系統,回答出 kafka 的系統特點,leader 和 follower 的關系,消息讀寫的順序即可。

17、kafka 如何減少資料丢失

Kafka到底會不會丢資料(data loss)? 通常不會,但有些情況下的确有可能會發生。下面的參數配置及Best practice清單可以較好地保證資料的持久性(當然是trade-off,犧牲了吞吐量)。

  • block.on.buffer.full = true
  • acks = all
  • retries = MAX_VALUE
  • max.in.flight.requests.per.connection = 1
  • 使用KafkaProducer.send(record, callback)
  • callback邏輯中顯式關閉producer:close(0)
  • unclean.leader.election.enable=false
  • replication.factor = 3
  • min.insync.replicas = 2
  • replication.factor > min.insync.replicas
  • enable.auto.commit=false
  • 消息處理完成之後再送出位移

18、kafka 如何不消費重複資料?比如扣款,我們不能重複的扣。

其實還是得結合業務來思考,我這裡給幾個思路:

比如你拿個資料要寫庫,你先根據主鍵查一下,如果這資料都有了,你就别插入了,update 一下好吧。

比如你是寫 Redis,那沒問題了,反正每次都是 set,天然幂等性。

比如你不是上面兩個場景,那做的稍微複雜一點,你需要讓生産者發送每條資料的時候,裡面加一個全局唯一的 id,類似訂單 id 之類的東西,然後你這裡消費到了之後,先根據這個 id 去比如 Redis 裡查一下,之前消費過嗎?如果沒有消費過,你就處理,然後這個 id 寫 Redis。如果消費過了,那你就别處理了,保證别重複處理相同的消息即可。

比如基于資料庫的唯一鍵來保證重複資料不會重複插入多條。因為有唯一鍵限制了,重複資料插入隻會報錯,不會導緻資料庫中出現髒資料。

本内容由個人從參考資料收集而來,可能有不準确的地方,還請各位多多指正,謝謝!

以下還有更多一線學習資料(2T),關注我的公衆号,免費領取,如:

【Java面試系列】kafka面試題熱門系列:目錄1.kafka 面試題2.題目解析 
【Java面試系列】kafka面試題熱門系列:目錄1.kafka 面試題2.題目解析 

以上資料,都是我個人平時收集而來,有網盤存儲,長期有效!有興趣的同學,可以掃碼關注我的個人公衆号:時代名猿,回複關鍵字:wyzl ,領取一線資料!

【Java面試系列】kafka面試題熱門系列:目錄1.kafka 面試題2.題目解析 

繼續閱讀