1. 程式人生 > 其它 >JAVA面試題--Kafka

JAVA面試題--Kafka

Kafka

1.為什麼要使用 kafka?為什麼要使用訊息佇列?

緩衝和削峰:上游資料時有突發流量,下游可能扛不住,或者下游沒有足夠多的機器來保證冗餘,kafka在中間可以起到一個緩衝的作用,把訊息暫存在kafka中,下游服務就可以按照自己的節奏進行慢慢處理。
解耦和擴充套件性:專案開始的時候,並不能確定具體需求。訊息佇列可以作為一個介面層,解耦重要的業務流程。只需要遵守約定,針對資料程式設計即可獲取擴充套件能力。
冗餘:可以採用一對多的方式,一個生產者釋出訊息,可以被多個訂閱topic的服務消費到,供多個毫無關聯的業務使用。
健壯性:訊息佇列可以堆積請求,所以消費端業務即使短時間死掉,也不會影響主要業務的正常進行。
非同步通訊:很多時候,使用者不想也不需要立即處理訊息。訊息佇列提供了非同步處理機制,允許使用者把一個訊息放入佇列,但並不立即處理它。想向佇列中放入多少訊息就放多少,然後在需要的時候再去處理它們。

2.Kafka中的ISR、AR又代表什麼?ISR的伸縮又指什麼?

ISR:In-Sync Replicas 副本同步佇列
AR:Assigned Replicas 所有副本
ISR是由leader維護,follower從leader同步資料有一些延遲(包括延遲時間replica.lag.time.max.ms和延遲條數replica.lag.max.messages兩個維度, 當前最新的版本0.10.x中只支援replica.lag.time.max.ms這個維度),任意一個超過閾值都會把follower剔除出ISR, 存入OSR(Outof-Sync Replicas)列表,新加入的follower也會先存放在OSR中。AR=ISR+OSR。

3.kafka中的broker 是幹什麼的?

broker 是訊息的代理,Producers往Brokers裡面的指定Topic中寫訊息,Consumers從Brokers裡面拉取指定Topic的訊息,然後進行業務處理,broker在中間起到一個代理儲存訊息的中轉站。

4.kafka中的 zookeeper 起到什麼作用?可以不用zookeeper麼?

zookeeper 是一個分散式的協調元件,早期版本的kafka用zk做meta資訊儲存,consumer的消費狀態,group的管理以及 offset的值。考慮到zk本身的一些因素以及整個架構較大概率存在單點問題,新版本中逐漸弱化了zookeeper的作用。新的consumer使用了kafka內部的group coordination協議,也減少了對zookeeper的依賴,但是broker依然依賴於ZK,zookeeper 在kafka中還用來選舉controller 和 檢測broker是否存活等等。

5.kafka follower如何與leader同步資料?

Kafka的複製機制既不是完全的同步複製,也不是單純的非同步複製。完全同步複製要求All Alive Follower都複製完,這條訊息才會被認為commit,這種複製方式極大的影響了吞吐率。而非同步複製方式下,Follower非同步的從Leader複製資料,資料只要被Leader寫入log就被認為已經commit,這種情況下,如果leader掛掉,會丟失資料,kafka使用ISR的方式很好的均衡了確保資料不丟失以及吞吐率。Follower可以批量的從Leader複製資料,而且Leader充分利用磁碟順序讀以及send file(zero copy)機制,這樣極大的提高複製效能,內部批量寫磁碟,大幅減少了Follower與Leader的訊息量差。

6.什麼情況下一個 broker 會從 ISR 中被踢出去?

leader會維護一個與其基本保持同步的Replica列表,該列表稱為ISR(in-sync Replica),每個Partition都會有一個ISR,而且是由leader動態維護 ,如果一個follower比一個leader落後太多,或者超過一定時間未發起資料複製請求,則leader將其重ISR中移除 。

7.kafka 為什麼那麼快?

Cache Filesystem Cache PageCache快取
順序。 由於現代的作業系統提供了預讀和寫技術,磁碟的順序寫大多數情況下比隨機寫記憶體還要快。
Zero-copy。零拷技術減少拷貝次數
Batching of Messages 批量量處理。合併小的請求,然後以流的方式進行互動,直頂網路上限。
Pull 拉模式。使用拉模式進行訊息的獲取消費,與消費端處理能力相符。

8.kafka producer如何優化打入速度?

增加執行緒
提高 batch.size
增加更多 producer 例項
增加 partition 數
設定 acks=-1 時,如果延遲增大:可以增大 num.replica.fetchers(follower 同步資料的執行緒數)來調解;
跨資料中心的傳輸:增加 socket 緩衝區設定以及 OS tcp 緩衝區設定。

9.kafka producer 打資料,ack 為 0, 1, -1 的時候代表啥, 設定 -1 的時候,什麼情況下,leader 會認為一條訊息 commit 了

1(預設):資料傳送到Kafka後,經過leader成功接收訊息的的確認,就算是傳送成功了。在這種情況下,如果leader宕機了,則會丟失資料。
0:生產者將資料傳送出去就不管了,不去等待任何返回。這種情況下資料傳輸效率最高,但是資料可靠性確是最低的。
-1:producer需要等待ISR中的所有follower都確認接收到資料後才算一次傳送完成,可靠性最高。當ISR中所有Replica都向Leader傳送ACK時,leader才commit,這時候producer才能認為一個請求中的訊息都commit了。

10.kafka unclean 配置代表啥?會對 spark streaming 消費有什麼影響?

unclean.leader.election.enable 為true的話,意味著非ISR集合的broker 也可以參與選舉,這樣有可能就會丟資料,spark streaming在消費過程中拿到的 end offset 會突然變小,導致 spark streaming job掛掉。如果unclean.leader.election.enable引數設定為true,就有可能發生資料丟失和資料不一致的情況,Kafka的可靠性就會降低;而如果unclean.leader.election.enable引數設定為false,Kafka的可用性就會降低。

11.如果leader crash時,ISR為空怎麼辦?

kafka在Broker端提供了一個配置引數:unclean.leader.election,這個引數有兩個值:
true(預設):允許不同步副本成為leader,由於不同步副本的訊息較為滯後,此時成為leader,可能會出現訊息不一致的情況。
false:不允許不同步副本成為leader,此時如果發生ISR列表為空,會一直等待舊leader恢復,降低了可用性。

12.kafka的message格式是什麼樣的?

一個Kafka的Message由一個固定長度的header和一個變長的訊息體body組成。
header部分由一個位元組的magic(檔案格式)和四個位元組的CRC32(用於判斷body訊息體是否正常)構成。
當magic的值為1的時候,會在magic和crc32之間多一個位元組的資料:attributes(儲存一些相關屬性,比如是否壓縮、壓縮格式等等);如果magic的值為0,那麼不存在attributes屬性。
body是由N個位元組構成的一個訊息體,包含了具體的key/value訊息。

13.kafka中consumer group 是什麼概念?

同樣是邏輯上的概念,是Kafka實現單播和廣播兩種訊息模型的手段。同一個topic的資料,會廣播給不同的group;同一個group中的worker,只有一個worker能拿到這個資料。換句話說,對於同一個topic,每個group都可以拿到同樣的所有資料,但是資料進入group後只能被其中的一個worker消費。group內的worker可以使用多執行緒或多程序來實現,也可以將程序分散在多臺機器上,worker的數量通常不超過partition的數量,且二者最好保持整數倍關係,因為Kafka在設計時假定了一個partition只能被一個worker消費(同一group內)。

14.Kafka中的訊息是否會丟失和重複消費?

要確定Kafka的訊息是否丟失或重複,從兩個方面分析入手:訊息傳送和訊息消費。

1)訊息傳送
Kafka訊息傳送有兩種方式:同步(sync)和非同步(async),預設是同步方式,可通過producer.type屬性進行配置。Kafka通過配置request.required.acks屬性來確認訊息的生產:

0---表示不進行訊息接收是否成功的確認;
1---表示當Leader接收成功時確認;
-1---表示Leader和Follower都接收成功時確認;
綜上所述,有6種訊息生產的情況,下面分情況來分析訊息丟失的場景:

(1)acks=0,不和Kafka叢集進行訊息接收確認,則當網路異常、緩衝區滿了等情況時,訊息可能丟失;

(2)acks=1、同步模式下,只有Leader確認接收成功後但掛掉了,副本沒有同步,資料可能丟失;

2)訊息消費

Kafka訊息消費有兩個consumer介面,Low-level API和High-level API:

Low-level API:消費者自己維護offset等值,可以實現對Kafka的完全控制;

High-level API:封裝了對parition和offset的管理,使用簡單;

如果使用高階介面High-level API,可能存在一個問題就是當訊息消費者從叢集中把訊息取出來、並提交了新的訊息offset值後,還沒來得及消費就掛掉了,那麼下次再消費時之前沒消費成功的訊息就“詭異”的消失了;

3)解決辦法

針對訊息丟失:同步模式下,確認機制設定為-1,即讓訊息寫入Leader和Follower之後再確認訊息傳送成功;非同步模式下,為防止緩衝區滿,可以在配置檔案設定不限制阻塞超時時間,當緩衝區滿時讓生產者一直處於阻塞狀態;
針對訊息重複:將訊息的唯一標識儲存到外部介質中,每次消費時判斷是否處理過即可。

15.為什麼Kafka不支援讀寫分離?

在 Kafka 中,生產者寫入訊息、消費者讀取訊息的操作都是與 leader 副本進行互動的,從 而實現的是一種主寫主讀的生產消費模型。

Kafka 並不支援主寫從讀,因為主寫從讀有 2 個很明 顯的缺點:

(1)資料一致性問題。資料從主節點轉到從節點必然會有一個延時的時間視窗,這個時間 視窗會導致主從節點之間的資料不一致。某一時刻,在主節點和從節點中 A 資料的值都為 X, 之後將主節點中 A 的值修改為 Y,那麼在這個變更通知到從節點之前,應用讀取從節點中的 A 資料的值並不為最新的 Y,由此便產生了資料不一致的問題。

(2)延時問題。類似 Redis 這種元件,資料從寫入主節點到同步至從節點中的過程需要經 歷網路→主節點記憶體→網路→從節點記憶體這幾個階段,整個過程會耗費一定的時間。而在 Kafka 中,主從同步會比 Redis 更加耗時,它需要經歷網路→主節點記憶體→主節點磁碟→網路→從節 點記憶體→從節點磁碟這幾個階段。對延時敏感的應用而言,主寫從讀的功能並不太適用。

16.Kafka中是怎麼體現訊息順序性的?

kafka每個partition中的訊息在寫入時都是有序的,消費時,每個partition只能被每一個group中的一個消費者消費,保證了消費時也是有序的。
整個topic不保證有序。如果為了保證topic整個有序,那麼將partition調整為1。

17.kafka如何實現延遲佇列?

Kafka並沒有使用JDK自帶的Timer或者DelayQueue來實現延遲的功能,而是基於時間輪自定義了一個用於實現延遲功能的定時器(SystemTimer)。JDK的Timer和DelayQueue插入和刪除操作的平均時間複雜度為O(nlog(n)),並不能滿足Kafka的高效能要求,而基於時間輪可以將插入和刪除操作的時間複雜度都降為O(1)。時間輪的應用並非Kafka獨有,其應用場景還有很多,在Netty、Akka、Quartz、Zookeeper等元件中都存在時間輪的蹤影。

底層使用陣列實現,陣列中的每個元素可以存放一個TimerTaskList物件。TimerTaskList是一個環形雙向連結串列,在其中的連結串列項TimerTaskEntry中封裝了真正的定時任務TimerTask.

Kafka中到底是怎麼推進時間的呢?Kafka中的定時器藉助了JDK中的DelayQueue來協助推進時間輪。具體做法是對於每個使用到的TimerTaskList都會加入到DelayQueue中。Kafka中的TimingWheel專門用來執行插入和刪除TimerTaskEntry的操作,而DelayQueue專門負責時間推進的任務。再試想一下,DelayQueue中的第一個超時任務列表的expiration為200ms,第二個超時任務為840ms,這裡獲取DelayQueue的隊頭只需要O(1)的時間複雜度。如果採用每秒定時推進,那麼獲取到第一個超時的任務列表時執行的200次推進中有199次屬於“空推進”,而獲取到第二個超時任務時有需要執行639次“空推進”,這樣會無故空耗機器的效能資源,這裡採用DelayQueue來輔助以少量空間換時間,從而做到了“精準推進”。Kafka中的定時器真可謂是“知人善用”,用TimingWheel做最擅長的任務新增和刪除操作,而用DelayQueue做最擅長的時間推進工作,相輔相成。

18.什麼是消費者組?

消費者組是 Kafka 獨有的概念,如果面試官問這 個,就說明他對此是有一定了解的。我先給出標準答案:
1、定義:即消費者組是 Kafka 提供的可擴充套件且具有容錯性的消費者機制。
2、原理:在 Kafka 中,消費者組是一個由多個消費者例項 構成的組。多個例項共同訂閱若干個主題,實現共同消費。同一個組下的每個例項都配置有 相同的組 ID,被分配不同的訂閱分割槽。當某個例項掛掉的時候,其他例項會自動地承擔起 它負責消費的分割槽。

此時,又有一個小技巧給到你:消費者組的題目,能夠幫你在某種程度上掌控下面的面試方
向。

如果你擅長位移值原理,就不妨再提一下消費者組的位移提交機制;
如果你擅長 Kafka Broker,可以提一下消費者組與 Broker 之間的互動;
如果你擅長與消費者組完全不相關的 Producer,那麼就可以這麼說:“消費者組要消 費的資料完全來自於 Producer 端生產的訊息,我對 Producer 還是比較熟悉的。”

19.解釋下 Kafka 中位移(offset)的作用。

在 Kafka 中,每個 主題分割槽下的每條訊息都被賦予了一個唯一的 ID 數值,用於標識它在分割槽中的位置。這個 ID 數值,就被稱為位移,或者叫偏移量。一旦訊息被寫入到分割槽日誌,它的位移值將不能 被修改。
答完這些之後,你還可以把整個面試方向轉移到你希望的地方。常見方法有以下 3 種:
如果你深諳 Broker 底層日誌寫入的邏輯,可以強調下訊息在日誌中的存放格式;
如果你明白位移值一旦被確定不能修改,可以強調下“Log Cleaner 元件都不能影響位 移值”這件事情;
如果你對消費者的概念還算熟悉,可以再詳細說說位移值和消費者位移值之間的區別。

20.闡述下 Kafka 中的領導者副本(Leader Replica)和追隨者副本 (Follower Replica)的區別。

這道題表面上是考核你對 Leader 和 Follower 區別的理解,但很容易引申到 Kafka 的同步 機制上。因此,我建議你主動出擊,一次性地把隱含的考點也答出來,也許能夠暫時把面試 官“唬住”,並體現你的專業性。

你可以這麼回答:Kafka 副本當前分為領導者副本和追隨者副本。只有 Leader 副本才能 對外提供讀寫服務,響應 Clients 端的請求。Follower 副本只是採用拉(PULL)的方 式,被動地同步 Leader 副本中的資料,並且在 Leader 副本所在的 Broker 宕機後,隨時 準備應聘 Leader 副本。

通常來說,回答到這個程度,其實才只說了 60%,因此,我建議你再回答兩個額外的加分 項。

強調 Follower 副本也能對外提供讀服務。自 Kafka 2.4 版本開始,社群通過引入新的 Broker 端引數,允許 Follower 副本有限度地提供讀服務。
強調 Leader 和 Follower 的訊息序列在實際場景中不一致。很多原因都可能造成 Leader 和 Follower 儲存的訊息序列不一致,比如程式 Bug、網路問題等。這是很嚴重 的錯誤,必須要完全規避。你可以補充下,之前確保一致性的主要手段是高水位機制, 但高水位值無法保證 Leader 連續變更場景下的資料一致性,因此,社群引入了 Leader Epoch 機制,來修復高水位值的弊端。關於“Leader Epoch 機制”,國內的資料不是 很多,它的普及度遠不如高水位,不妨大膽地把這個概念秀出來,力求驚豔一把。

21.如何設定 Kafka 能接收的最大訊息的大小?

這道題除了要回答消費者端的引數設定之外,一定要加上 Broker 端的設定,這樣才算完整。畢竟,如果 Producer 都不能向 Broker 端傳送資料很大的訊息,又何來消費一說呢? 因此,你需要同時設定 Broker 端引數和 Consumer 端引數。

Broker 端引數:message.max.bytes、max.message.bytes(主題級別)和 replica.fetch.max.bytes。
Consumer 端引數:fetch.message.max.bytes。
Broker 端的最後一個引數比較容易遺漏。我們必須調整 Follower 副本能夠接收的最大消 息的大小,否則,副本同步就會失敗。因此,把這個答出來的話,就是一個加分項。

22.監控 Kafka 的框架都有哪些?

面試官其實是在 考察你對監控框架的瞭解廣度,或者說,你是否知道很多能監控 Kafka 的框架或方法。下面這些就是 Kafka 發展歷程上比較有名氣的監控系統。

Kafka Manager:應該算是最有名的專屬 Kafka 監控框架了,是獨立的監控系統。
Kafka Monitor:LinkedIn 開源的免費框架,支援對叢集進行系統測試,並實時監控測
試結果。
CruiseControl:也是 LinkedIn 公司開源的監控框架,用於實時監測資源使用率,以及 提供常用運維操作等。無 UI 介面,只提供 REST API。
JMX 監控:由於 Kafka 提供的監控指標都是基於 JMX 的,因此,市面上任何能夠整合 JMX 的框架都可以使用,比如 Zabbix 和 Prometheus。
已有大資料平臺自己的監控體系:像 Cloudera 提供的 CDH 這類大資料平臺,天然就提 供 Kafka 監控方案。
JMXTool:社群提供的命令列工具,能夠實時監控 JMX 指標。答上這一條,屬於絕對 的加分項,因為知道的人很少,而且會給人一種你對 Kafka 工具非常熟悉的感覺。如果 你暫時不瞭解它的用法,可以在命令列以無引數方式執行一下kafka-run-class.sh kafka.tools.JmxTool,學習下它的用法。

23.Broker 的 Heap Size 如何設定?

如何設定 Heap Size 的問題,其實和 Kafka 關係不大,它是一類非常通用的面試題目。一 旦你應對不當,面試方向很有可能被引到 JVM 和 GC 上去,那樣的話,你被問住的機率就 會增大。因此,我建議你簡單地介紹一下 Heap Size 的設定方法,並把重點放在 Kafka Broker 堆大小設定的最佳實踐上。

比如,你可以這樣回覆:任何 Java 程序 JVM 堆大小的設定都需要仔細地進行考量和測 試。一個常見的做法是,以預設的初始 JVM 堆大小執行程式,當系統達到穩定狀態後,手動觸發一次 Full GC,然後通過 JVM 工具檢視 GC 後的存活物件大小。之後,將堆大小設 置成存活物件總大小的 1.5~2 倍。對於 Kafka 而言,這個方法也是適用的。不過,業界有 個最佳實踐,那就是將 Broker 的 Heap Size 固定為 6GB。經過很多公司的驗證,這個大 小是足夠且良好的。

24.如何估算 Kafka 叢集的機器數量?

這道題目考查的是機器數量和所用資源之間的關聯關係。所謂資源,也就是 CPU、記憶體、磁碟和頻寬。

通常來說,CPU 和記憶體資源的充足是比較容易保證的,因此,你需要從磁碟空間和頻寬佔用兩個維度去評估機器數量。

在預估磁碟的佔用時,你一定不要忘記計算副本同步的開銷。如果一條訊息佔用 1KB 的磁 盤空間,那麼,在有 3 個副本的主題中,你就需要 3KB 的總空間來儲存這條訊息。顯式地 將這些考慮因素答出來,能夠彰顯你考慮問題的全面性,是一個難得的加分項。

對於評估頻寬來說,常見的頻寬有 1Gbps 和 10Gbps,但你要切記,這兩個數字僅僅是最大值。因此,你最好和麵試官確認一下給定的頻寬是多少。然後,明確闡述出當頻寬佔用接 近總頻寬的 90% 時,丟包情形就會發生。這樣能顯示出你的網路基本功。

25.Leader 總是 -1,怎麼破?

在生產環境中,你一定碰到過“某個主題分割槽不能工作了”的情形。使用命令列檢視狀態的 話,會發現 Leader 是 -1,於是,你使用各種命令都無濟於事,最後只能用“重啟大 法”。

但是,有沒有什麼辦法,可以不重啟叢集,就能解決此事呢?這就是此題的由來。

我直接給答案:刪除 ZooKeeper 節點 /controller,觸發 Controller 重選舉。 Controller 重選舉能夠為所有主題分割槽重刷分割槽狀態,可以有效解決因不一致導致的 Leader 不可用問題。我幾乎可以斷定,當面試官問出此題時,要麼就是他真的不知道怎麼 解決在向你尋求答案,要麼他就是在等你說出這個答案。所以,千萬別一上來就說“來個重 啟”之類的話。

26.LEO、LSO、AR、ISR、HW 都表示什麼含義?

LEO:Log End Offset。日誌末端位移值或末端偏移量,表示日誌下一條待插入訊息的 位移值。舉個例子,如果日誌有 10 條訊息,位移值從 0 開始,那麼,第 10 條訊息的位 移值就是 9。此時,LEO = 10。
LSO:Log Stable Offset。這是 Kafka 事務的概念。如果你沒有使用到事務,那麼這個 值不存在(其實也不是不存在,只是設定成一個無意義的值)。該值控制了事務型消費 者能夠看到的訊息範圍。它經常與 Log Start Offset,即日誌起始位移值相混淆,因為 有些人將後者縮寫成 LSO,這是不對的。在 Kafka 中,LSO 就是指代 Log Stable Offset。
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 中移除。
HW:高水位值(High watermark)。這是控制消費者可讀取訊息範圍的重要欄位。一 個普通消費者只能“看到”Leader 副本上介於 Log Start Offset 和 HW(不含)之間的 所有訊息。水位以上的訊息是對消費者不可見的。關於 HW,問法有很多,我能想到的 最高階的問法,就是讓你完整地梳理下 Follower 副本拉取 Leader 副本、執行同步機制 的詳細步驟。這就是我們的第 20 道題的題目,一會兒我會給出答案和解析。

27.Kafka 能手動刪除訊息嗎?

其實,Kafka 不需要使用者手動刪除訊息。它本身提供了留存策略,能夠自動刪除過期訊息。 當然,它是支援手動刪除訊息的。因此,你最好從這兩個維度去回答。

對於設定了 Key 且引數 cleanup.policy=compact 的主題而言,我們可以構造一條 <Key,null> 的訊息傳送給 Broker,依靠 Log Cleaner 元件提供的功能刪除掉該 Key 的訊息。
對於普通主題而言,我們可以使用 kafka-delete-records 命令,或編寫程式呼叫 Admin.deleteRecords 方法來刪除訊息。這兩種方法殊途同歸,底層都是呼叫 Admin 的 deleteRecords 方法,通過將分割槽 Log Start Offset 值抬高的方式間接刪除訊息。

28.consumer_offsets 是做什麼用的?

這是一個內部主題,公開的官網資料很少涉及到。因此,我認為,此題屬於面試官炫技一類 的題目。你要小心這裡的考點:該主題有 3 個重要的知識點,你一定要全部答出來,才會顯得對這塊知識非常熟悉。

它是一個內部主題,無需手動干預,由 Kafka 自行管理。當然,我們可以建立該主題。

它的主要作用是負責註冊消費者以及儲存位移值。可能你對儲存位移值的功能很熟悉, 但其實該主題也是儲存消費者元資料的地方。千萬記得把這一點也回答上。另外,這裡 的消費者泛指消費者組和獨立消費者,而不僅僅是消費者組。

Kafka 的 GroupCoordinator 元件提供對該主題完整的管理功能,包括該主題的建立、 寫入、讀取和 Leader 維護等。

29.分割槽 Leader 選舉策略有幾種?

分割槽的 Leader 副本選舉對使用者是完全透明的,它是由 Controller 獨立完成的。你需要回答的是,在哪些場景下,需要執行分割槽 Leader 選舉。每一種場景對應於一種選舉策略。當前,Kafka 有 4 種分割槽 Leader 選舉策略。

OfflinePartition Leader 選舉:每當有分割槽上線時,就需要執行 Leader 選舉。所謂的分割槽上線,可能是建立了新分割槽,也可能是之前的下線分割槽重新上線。這是最常見的分割槽 Leader 選舉場景。

ReassignPartition Leader 選舉:當你手動執行 kafka-reassign-partitions 命令,或者是呼叫 Admin 的 alterPartitionReassignments 方法執行分割槽副本重分配時,可能觸發此類選舉。假設原來的 AR 是[1,2,3],Leader 是 1,當執行副本重分配後,副本集 合 AR 被設定成[4,5,6],顯然,Leader 必須要變更,此時會發生 Reassign Partition Leader 選舉。

PreferredReplicaPartition Leader 選舉:當你手動執行 kafka-preferred-replica- election 命令,或自動觸發了 Preferred Leader 選舉時,該類策略被啟用。所謂的 Preferred Leader,指的是 AR 中的第一個副本。比如 AR 是[3,2,1],那麼, Preferred Leader 就是 3。

ControlledShutdownPartition Leader 選舉:當 Broker 正常關閉時,該 Broker 上 的所有 Leader 副本都會下線,因此,需要為受影響的分割槽執行相應的 Leader 選舉。

這 4 類選舉策略的大致思想是類似的,即從 AR 中挑選首個在 ISR 中的副本,作為新 Leader。當然,個別策略有些微小差異。不過,回答到這種程度,應該足以應付面試官 了。畢竟,微小差別對選舉 Leader 這件事的影響很小。

30.Kafka 的哪些場景中使用了零拷貝(Zero Copy)?

Zero Copy 是特別容易被問到的高階題目。在 Kafka 中,體現 Zero Copy 使用場景的地方有兩處:基於 mmap 的索引和日誌檔案讀寫所用的 TransportLayer。

先說第一個。索引都是基於 MappedByteBuffer 的,也就是讓使用者態和核心態共享核心態 的資料緩衝區,此時,資料不需要複製到使用者態空間。不過,mmap 雖然避免了不必要的 拷貝,但不一定就能保證很高的效能。在不同的作業系統下,mmap 的建立和銷燬成本可 能是不一樣的。很高的建立和銷燬開銷會抵消 Zero Copy 帶來的效能優勢。由於這種不確 定性,在 Kafka 中,只有索引應用了 mmap,最核心的日誌並未使用 mmap 機制。

再說第二個。TransportLayer 是 Kafka 傳輸層的介面。它的某個實現類使用了 FileChannel 的 transferTo 方法。該方法底層使用 sendfile 實現了 Zero Copy。對 Kafka 而言,如果 I/O 通道使用普通的 PLAINTEXT,那麼,Kafka 就可以利用 Zero Copy 特 性,直接將頁快取中的資料傳送到網絡卡的 Buffer 中,避免中間的多次拷貝。相反,如果 I/O 通道啟用了 SSL,那麼,Kafka 便無法利用 Zero Copy 特性了。

31.如何調優 Kafka?

回答任何調優問題的第一步,就是確定優化目標,並且定量給出目標!這點特別重要。對於 Kafka 而言,常見的優化目標是吞吐量、延時、永續性和可用性。每一個方向的優化思路都 是不同的,甚至是相反的。

確定了目標之後,還要明確優化的維度。有些調優屬於通用的優化思路,比如對作業系統、 JVM 等的優化;有些則是有針對性的,比如要優化 Kafka 的 TPS。我們需要從 3 個方向去考慮

Producer 端:增加 batch.size、linger.ms,啟用壓縮,關閉重試等。
Broker 端:增加 num.replica.fetchers,提升 Follower 同步 TPS,避免 Broker Full GC 等。
Consumer:增加 fetch.min.bytes 等

32.Controller 發生網路分割槽(Network Partitioning)時,Kafka 會怎麼樣?

這道題目能夠誘發我們對分散式系統設計、CAP 理論、一致性等多方面的思考。不過,針 對故障定位和分析的這類問題,我建議你首先言明“實用至上”的觀點,即不論怎麼進行理論分析,永遠都要以實際結果為準。一旦發生 Controller 網路分割槽,那麼,第一要務就是 檢視叢集是否出現“腦裂”,即同時出現兩個甚至是多個 Controller 元件。這可以根據 Broker 端監控指標 ActiveControllerCount 來判斷。

現在,我們分析下,一旦出現這種情況,Kafka 會怎麼樣。

由於 Controller 會給 Broker 傳送 3 類請求,即LeaderAndIsrRequest、 StopReplicaRequest 和 UpdateMetadataRequest,因此,一旦出現網路分割槽,這些請求將不能順利到達 Broker 端。這將影響主題的建立、修改、刪除操作的資訊同步,表現為 叢集彷彿僵住了一樣,無法感知到後面的所有操作。因此,網路分割槽通常都是非常嚴重的問 題,要趕快修復。

33.Java Consumer 為什麼採用單執行緒來獲取訊息?

在回答之前,如果先把這句話說出來,一定會加分:Java Consumer 是雙執行緒的設計。一 個執行緒是使用者主執行緒,負責獲取訊息;另一個執行緒是心跳執行緒,負責向 Kafka 彙報消費者 存活情況。將心跳單獨放入專屬的執行緒,能夠有效地規避因訊息處理速度慢而被視為下線 的“假死”情況。

單執行緒獲取訊息的設計能夠避免阻塞式的訊息獲取方式。單執行緒輪詢方式容易實現非同步非阻塞式,這樣便於將消費者擴充套件成支援實時流處理的操作運算元。因為很多實時流處理操作運算元都不能是阻塞式的。另外一個可能的好處是,可以簡化程式碼的開發。多執行緒互動的程式碼是非常容易出錯的。

34.簡述 Follower 副本訊息同步的完整流程。

首先,Follower 傳送 FETCH 請求給 Leader。接著,Leader 會讀取底層日誌檔案中的消 息資料,再更新它記憶體中的 Follower 副本的 LEO 值,更新為 FETCH 請求中的 fetchOffset 值。最後,嘗試更新分割槽高水位值。Follower 接收到 FETCH 響應之後,會把 訊息寫入到底層日誌,接著更新 LEO 和 HW 值。

Leader 和 Follower 的 HW 值更新時機是不同的,Follower 的 HW 更新永遠落後於 Leader 的 HW。這種時間上的錯配是造成各種不一致的原因。

線上刷題小程式

參考資料

https://blog.csdn.net/qq_28900249/article/details/90346599
https://www.jianshu.com/p/511962462e58