kafka常見面試題


1.Kafka 中的 ISR(InSyncRepli)、OSR(OutSyncRepli)、AR(AllRepli)代表什么?

  1、AR = ISR+OSR

ISR: 

  kafka 使用多副本來保證消息不丟失,多副本就涉及到kafka的復制機制,在一個超大規模的集群中,時不時地這個點磁盤壞了,那個點cpu負載高了,出現各種各樣的問題,多個副本之間的復制,如果想完全自動化容錯,就要做一些考量和取舍了。我們舉個例子說明下運維中面對的復雜性,我們都知道 kafka 有個 ISR集合,我先說明下這個概念:

kafka不是完全同步,也不是完全異步,是一種ISR機制:

1. leader會維護一個與其基本保持同步的Replica列表,該列表稱為ISR(in-sync Replica),每個Partition都會有一個ISR,而且是由leader動態維護

2. 如果一個follower比一個leader落后太多,或者超過一定時間未發起數據復制請求,則leader將其重ISR中移除

3. 當ISR中所有Replica都向Leader發送ACK時,leader才commit,這時候producer才能認為一個請求中的消息都commit了。

  kafka中的副本機制是以分區粒度進行復制的,我們在kafka中創建 topic的時候,都可以設置一個復制因子,這個復制因子決定着分區副本的個數,如果leader 掛掉了,kafka 會把分區主節點failover到其他副本節點,這樣就能保證這個分區的消息是可用的。leader節點負責接收producer 打過來的消息,其他副本節點(follower)從主節點上拷貝消息。

  存在的問題:

  從上面的情況來看,兩個參數看似已經足夠了,如果一個副本超過 replica.lag.time.max.ms 還沒有發送fetch同步請求, 可以認為這個副本節點卡住了,然后踢出去,但是還有一種比較特殊的情況沒有考慮到,我們上文中設置 replica.lag.max.messages 為4,之所以設置為 4, 是我們已經知道 producer 每次請求打過來的消息數都在 4 以下,如果我們的參數是作用於多個 topic 的情況,那么這個 producer 最大打過來的消息數目就不好估計了,或者說在經常出現流量抖動的情況下,就會出現一個什么情況呢,我們還是使用例子說明:

  如果我們的 topic — foo 的 producer 因為流量抖動打過來一個 包含 4條消息的請求,我們設置的 replica.lag.max.messages 還是為4, 這個時候,所有的 follower 都會因為超出落后條數被踢出 ISR集合。

  然后,因為 follower 是正常的,所以下一次 fetch 請求就會又追上 leader, 這時候就會再次加入 ISR 集合,如果經常性的抖動,就會不斷的移入移出ISR集合,會造成令人頭疼的 告警轟炸。

  kafka 給出的方案是這樣的,對 replica.lag.time.max.ms 這個配置的含義做了增強,和之前一樣,如果 follower 卡住超過這個時間不發送fetch請求, 會被踢出ISR集合,新的增強邏輯是,在 follower 落后 leader 超過 eplica.lag.max.messages 條消息的時候,不會立馬踢出ISR 集合,而是持續落后超過 replica.lag.time.max.ms 時間,才會被踢出

2.Kafka 中的 HW、LEO 等分別代表什么?

  

  • LEO:即日志末端位移(log end offset),記錄了該副本底層日志(log)中下一條消息的位移值。注意是下一條消息!也就是說,如果LEO=10,那么表示該副本保存了10條消息,位移值范圍是[0, 9]。
  • High Watermark(高水位線)以下簡稱HW,表示消息被leader和ISR內的follower都確認commit寫入本地log,所以在HW位置以下的消息都可以被消費(不會丟失)。
Kafka復制協議有兩個階段,第一階段,follower從leader獲取到消息;第二階段,在下一輪的RPC中向leader發送fetch request確認收到消息。假設其他的follower也都確認了,那么leader會更新HW,並在接下來的RPC中響應給follower。
同時,在重啟一個follower時,這個follower可能會把日志截斷到HW處(意味着此follower將會刪除一些消息),然后從leader獲取消息。

正式有與Kafka的復制協議分兩個階段,導致使用高水位會出現數據丟失和數據不一致的問題,下面我們分別講一下這兩種問題:

①數據丟失【Scenario 1: High Watermark Truncation followed by Immediate Leader Election】

假設有A、B兩個Broker,初始時B為leader,A從B中取到消息m2,所以A中有消息m2了,但是由於在下一輪RPC中,A才會更新自己的HW,所以此時A的HW沒變。如果這時候A重啟了,他截取自己的日志到HW並發送一個fetch request到B。不幸的是,B這時宕機了,A成了新的leader,那么此時消息m2就會永久的丟失了。

②數據不一致:【Scenario 2: Replica Divergence on Restart after Multiple Hard Failures】

假設我們有兩個Broker,初始時A是leader,B是follower。A接收到m2消息,但B還沒來得及復制時,斷電了。過了一會,B重啟了,成為了leader,接收了m3消息,HW+1。然后A重啟了,截斷日志到高水位,但是此時的消息卻出現了不一致。

在0.11版本使用leader epoch解決這兩個問題。

3.Kafka 中是怎么體現消息順序性的?

1、Kafka只能保證分區內消息順序有序,無法保證全局有序。

  • 生產者:通過分區的leader副本負責數據順序寫入,來保證消息順序性。
  • 消費者:同一個分區內的消息只能被一個group里的一個消費者消費,保證分區內消費有序。

2、如何做到並發且全局有序?

  整體思路】想辦法讓需要保證順序的數據發送到同一個分區中,並增加生產者/消費者的並發度

  1. topic設置一個分區,發送端和消費端開啟多線程生產和消費:簡單但有熱點瓶頸問題。
  2. topic設置多個分區,自定義發送端的分區策略,數據發送不同分區,消費時按發送分區的順序消費,發送和消費端都啟動多線程來提高並發度
    1. 自義分區器,使得消息按分區號大小順序依次發送相同數量大小的數據
    2. 發送端和消費端啟動多個消費線程進行生產和消費
    3. 線程之間按分區號大小順序消費數據
    4. 【弊端】消費性能極大下降,無法真正並發

4.Kafka 中的分區器、序列化器、攔截器是否了解?它們之間的處理順序是什么?

   分區器:根據鍵值確定消息應該處於哪個分區中,默認情況下使用輪詢分區,可以自行實現分區器接口自定義分區邏輯
   序列化器:鍵序列化器和值序列化器,將鍵和值都轉為二進制流 還有反序列化器 將二進制流轉為指定類型數據
  攔截器:兩個方法 doSend()方法會在 序列化之前完成 ,onAcknowledgement()方法在消息確認或失敗時回調。 可以添加多個攔截器按順序執行。
 
  調用順序: 攔截器doSend() -> 序列化器 -> 分區器

5.Kafka 生產者客戶端的整體結構是什么樣子的?使用了幾個線程來處理?分別是什么?

 

  Kafka 的 Producer 發送消息采用的是異步發送的方式。在消息發送的過程中,涉及到了 兩個線程——main 線程和 Sender 線程,以及一個線程共享變量——RecordAccumulator。 main 線程將消息發送給 RecordAccumulator,Sender 線程不斷從 RecordAccumulator 中拉取 消息(已經分好區)發送到 Kafka broker

  https://www.cnblogs.com/wsw-seu/p/13458506.html

 

6.“消費組中的消費者個數如果超過 topic 的分區,那么就會有消費者消費不到數據”這句 話是否正確?

正確,生產環境中這樣做浪費資源。

 

7.消費者提交消費位移時提交的是當前消費到的最新消息的 offset 還是 offset+1?

  offset+1

下面這個例子,zk中,bbb主題,2個分區。還沒消費就會存一個0 offset。

 

 

 

8.有哪些情形會造成重復消費?

消費者 先處理消息,后提交offset(可能失敗)

9.那些情景會造成消息漏消費?

消費者 先提交offset,再處理消息(可能失敗)

 

10.當你使用 kafka-topics.sh 創建(刪除)了一個 topic 之后,Kafka 背后會執行什么邏輯?

1)會在 zookeeper 中的/brokers/topics 節點下創建一個新的 topic 節點,如:

/brokers/topics/first

2)觸發 Controller 的監聽程序
3)kafka Controller 負責 topic 的創建工作,並更新 metadata cache

 

 

11.topic 的分區數可不可以增加?如果可以怎么增加?如果不可以,那又是為什么?

可以增

當一個主題被創建之后,依然允許我們對其做一定的修改,比如修改分區個數、修改配置等,這個修改的功能就是由kafka-topics.sh腳本中的alter指令所提供。我們首先來看如何增加主題的分區數。

以前面的主題topic-config為例,當前分區數為1,修改為3,示例如下:

注意上面提示的告警信息:當主題中的消息包含有key時(即key不為null),根據key來計算分區的行為就會有所影響。當topic-config的分區數為1時,不管消息的key為何值,消息都會發往這一個分區中;當分區數增加到3時,那么就會根據消息的key來計算分區號,原本發往分區0的消息現在有可能會發往分區1或者分區2中。如此還會影響既定消息的順序,所以在增加分區數時一定要三思而后行。對於基於key計算的主題而言,建議在一開始就設置好分區數量,避免以后對其進行調整。

12.topic 的分區數可不可以減少?如果可以怎么減少?如果不可以,那又是為什么?

目前Kafka只支持增加分區數而不支持減少分區數。比如我們將主題topic-config的分區數修改為1,就會報出InvalidPartitionException的異常。

比如刪除掉的分區中的消息該作何處理?如果隨着分區一起消失則消息的可靠性得不到保障;如果需要保留則又需要考慮如何保留。直接存儲到現有分區的尾部,消息的時間戳就不會遞增,如此對於Spark、Flink這類需要消息時間戳(事件時間)的組件將會受到影響;如果分散插入到現有的分區中,那么在消息量很大的時候,內部的數據復制會占用很大的資源,而且在復制期間,此主題的可用性又如何得到保障?與

此同時,順序性問題、事務性問題、以及分區和副本的狀態機切換問題都是不得不面對的。反觀這個功能的收益點卻是很低,如果真的需要實現此類的功能,完全可以重新創建一個分區數較小的主題,然后將現有主題中的消息按照既定的邏輯復制過去即可。

雖然分區數不可以減少,但是分區對應的副本數是可以減少的,這個其實很好理解,你關閉一個副本時就相當於副本數減少了。

 

13.Kafka 有內部的 topic 嗎?如果有是什么?有什么所用?

kafka在0.10.x版本后默認將消費者組的位移(offset)提交到自帶的topic__consumer_offsets里面,當有消費者第一次消費kafka數據時就會自動創建,它的副本數不受集群配置的topic副本數限制,分區數默認50(可以配置),默認壓縮策略為compact


14.Kafka 分區分配的概念?

 

當遇到“分區分配”這個字眼的時候,一定要記住有三處地方,分別是生產者發送消息、消費者消費消息、創建主題

1、生產者的分區分配

  對於用戶而言,當調用send方法發送消息之后,消息就自然而然的發送到了broker中。其實在這一過程中,有可能還要經過攔截器、序列化器和分區器(Partitioner)的一系列作用之后才能被真正地發往broker。

  消息在發往broker之前是需要確定它所發往的分區的,如果消息ProducerRecord中指定了partition字段,那么就不需要分區器的作用,因為partition代表的就是所要發往的分區號。如果消息    
  ProducerRecord中沒有指定partition字段,那么就需要依賴分區器,根據key這個字段來計算partition的值。分區器的作用就是為消息分配分區。
   默認情況下,如果消息的key不為null,那么默認的分區器會對key進行哈希(采用MurmurHash2算法,具備高運算性能及低碰撞率),最終根據得到的哈希值來計算分區號,擁有相同key的消息會被寫入同一個分區。如果key為null,那么消息將會以輪詢的方式發往主題內的各個可用分區

2、消費者的分區分配

  在Kafka的默認規則中,每一個分區只能被同一個消費組中的一個消費者消費。消費者的分區分配是指為消費組中的消費者分配所訂閱主題中的分區。

Kafka自身提供了三種策略,分別為 RangeAssignorRoundRobinAssignor以及 StickyAssignor,其中 RangeAssignor為默認的分區分配策略

3、broker端的分區分配

  生產者的分區分配是指為每條消息指定其所要發往的分區,消費者中的分區分配是指為消費者指定其可以消費消息的分區,而這里的分區分配是指為集群制定創建主題時的分區副本分配方案,即在哪個broker中創建哪些分區的副本。分區分配是否均衡會影響到Kafka整體的負載均衡,具體還會牽涉到優先副本等概念。

15.簡述 Kafka 的日志目錄結構?

見深入理解kafka核心設計與實踐原理第5章日志存儲
16.如果我指定了一個 offset,Kafka Controller 怎么查找到對應的消息?

 

同上

17.聊一聊 Kafka Controller 的作用?

  Controller 作為 Kafka Server 端一個重要的組件,它的角色類似於其他分布式系統 Master 的角色,跟其他系統不一樣的是,Kafka 集群的任何一台 Broker 都可以作為 Controller,但是在一個集群中同時只會有一個 Controller 是 alive 狀態。Controller 在集群中負責的事務很多,比如:集群 meta 信息的一致性保證、Partition leader 的選舉、broker 上下線等都是由 Controller 來具體負責。

  

  Controller 是運行在 Broker 上的,任何一台 Broker 都可以作為 Controller,但是一個集群同時只能存在一個 Controller,也就意味着 Controller 與數據節點是在一起的,Controller 做的主要事情如下:

  1. Broker 的上線、下線處理;
  2. 新創建的 topic 或已有 topic 的分區擴容,處理分區副本的分配、leader 選舉;
  3. 管理所有副本的狀態機和分區的狀態機,處理狀態機的變化事件;
  4. topic 刪除、副本遷移、leader 切換等處理。


18.Kafka 中有那些地方需要選舉?這些地方的選舉策略又有哪些?

Kafka中的選舉大致可以分為三大類:控制器的選舉、分區leader的選舉以及消費者相關的選舉。

1、控制器的選舉

在Kafka集群中會有一個或多個broker,其中有一個broker會被選舉為控制器(Kafka Controller),它負責管理整個集群中所有分區和副本的狀態等工作。比如當某個分區的leader副本出現故障時,由控制器負責為該分區選舉新的leader副本。再比如當檢測到某個分區的ISR集合發生變化時,由控制器負責通知所有broker更新其元數據信息。

Kafka Controller的選舉是依賴Zookeeper來實現的,在Kafka集群中哪個broker能夠成功創建/controller這個臨時(EPHEMERAL)節點他就可以成為Kafka Controller。

2、分區leader的選舉

  分區leader副本的選舉由Kafka Controller 負責具體實施。當創建分區(創建主題或增加分區都有創建分區的動作)或分區上線(比如分區中原先的leader副本下線,此時分區需要選舉一個新的leader上線來對外提供服務)的時候都需要執行leader的選舉動作。

  基本思路是按照AR集合中副本的順序查找第一個存活的副本,並且這個副本在ISR集合中。一個分區的AR集合在分配的時候就被指定,並且只要不發生重分配的情況,集合內部副本的順序是保持不變的,而分區的ISR集合中副本的順序可能會改變。注意這里是根據AR的順序而不是ISR的順序進行選舉的。

  還有一些情況也會發生分區leader的選舉,比如當分區進行重分配(reassign)的時候也需要執行leader的選舉動作。這個思路比較簡單:從重分配的AR列表中找到第一個存活的副本,且這個副本在目前的ISR列表中。

  再比如當發生優先副本(preferred replica partition leader election)的選舉時,直接將優先副本設置為leader即可,AR集合中的第一個副本即為優先副本。

3、消費者相關的選舉

  組協調器GroupCoordinator需要為消費組內的消費者選舉出一個消費組的leader,這個選舉的算法也很簡單,分兩種情況分析。如果消費組內還沒有leader,那么第一個加入消費組的消費者即為消費組的leader。如果某一時刻leader消費者由於某些原因退出了消費組,那么會重新選舉一個新的leader。

19.失效副本是指什么?有那些應對措施?

  正常情況下,分區的所有副本都處於 ISR 集合中,但是難免會有異常情況發生,從而某些副本被剝離出 ISR 集合中。在 ISR 集合之外,也就是處於同步失效或功能失效(比如副本處於非存活狀態)的副本統稱為失效副本,失效副本對應的分區也就稱為同步失效分區,即 under-replicated 分區。

  可以參考  https://www.cnblogs.com/luozhiyun/p/12079527.html
20.Kafka 的哪些設計讓它有如此高的性能?

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM