面試必問之kafka

問題1:消息隊列的作用

1、 解耦

快遞小哥手上有很多快遞需要送,他每次都需要先電話一一確認收貨人是否有空、哪個時間段有空,然後再確定好送貨的方案。這樣完全依賴收貨人了!如果快遞一多,快遞小哥估計的忙瘋了……如果有了便利店,快遞小哥只需要將同一個小區的快遞放在同一個便利店,然後通知收貨人來取貨就可以了,這時候快遞小哥和收貨人就實現瞭解耦!

2、 異步

快遞小哥打電話給我後需要一直在你樓下等着,直到我拿走你的快遞他才能去送其他人的。快遞小哥將快遞放在小芳便利店後,又可以幹其他的活兒去了,不需要等待你到來而一直處於等待狀態。提高了工作的效率。

3、 削峯

假設雙十一我買了不同店裏的各種商品,而恰巧這些店發貨的快遞都不一樣,有中通、圓通、申通、各種通等……更巧的是他們都同時到貨了!中通的小哥打來電話叫我去北門取快遞、圓通小哥叫我去南門、申通小哥叫我去東門。我一時手忙腳亂……

我們能看到在系統需要交互的場景中,使用消息隊列中間件真的是好處多多,基於這種思路,就有了豐巢、菜鳥驛站等比小芳便利店更專業的“中間件”了。

問題2:Kafka中有哪幾個組件?

主題:Kafka主題是一堆或一組消息。

生產者:在Kafka,生產者發佈通信以及向Kafka主題發佈消息。

消費者:Kafka消費者訂閱了一個主題,並且還從主題中讀取和處理消息。

經紀人:在管理主題中的消息存儲時,我們使用Kafka Brokers。
在這裏插入圖片描述

問題3:簡單說一下ack機制

ack:producer收到多少broker的答覆纔算真的發送成功

  • 0表示producer無需等待leader的確認(吞吐最高、數據可靠性最差)
  • 1代表需要leader確認寫入它的本地log並立即確認
  • -1/all 代表所有的ISR都完成後確認(吞吐最低、數據可靠性最高)

問題4:Kafka 如何判斷節點是否存活

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

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

問題5:Kafka 消息是採用 Pull 模式,還是 Push 模式

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 阻塞知道新消息到達
(當然也可以阻塞知道消息的數量達到某個特定的量這樣就可以批量發)

問題6 能說一下leader選舉過程嗎

我們知道Zookeeper集羣中也有選舉機制,是通過Paxos算法,通過不同節點向其他節點發送信息來投票選舉出leader,但是Kafka的leader的選舉就沒有這麼複雜了。
Kafka的Leader選舉是通過在zookeeper上創建/controller臨時節點來實現leader選舉,並在該節點中寫入當前broker的信息
{“version”:1,”brokerid”:1,”timestamp”:”1512018424988”}
利用Zookeeper的強一致性特性,一個節點只能被一個客戶端創建成功,創建成功的broker即爲leader,即先到先得原則,leader也就是集羣中的controller,負責集羣中所有大小事務。
當leader和zookeeper失去連接時,臨時節點會刪除,而其他broker會監聽該節點的變化,當節點刪除時,其他broker會收到事件通知,重新發起leader選舉。

問題7: kafka什麼情況下會rebalance

rebalance 的觸發條件有五個。

  • 條件1:有新的consumer加入
  • 條件2:舊的consumer掛了
  • 條件3:coordinator掛了,集羣選舉出新的coordinator
  • 條件4:topic的partition新加
  • 條件5:consumer調用unsubscrible(),取消topic的訂閱

rebalance 發生時,Group 下所有 consumer 實例都會協調在一起共同參與,kafka 能夠保證儘量達到最公平的分配。但是 Rebalance 過程對 consumer group 會造成比較嚴重的影響。在 Rebalance 的過程中 consumer group 下的所有消費者實例都會停止工作,等待 Rebalance 過程完成。

問題7.1: 能簡單說一下rebalance過程嗎?

主要的流程如下:

  1. 發送GCR請求尋找Coordinator:這個過程主要會向集羣中負載最小的broker發起請求,等待成功返回後,那麼該Broker將作爲Coordinator,嘗試連接該Coordinator
  2. 發送JGR請求加入該組:當成功找到Coordinator後,那麼就要發起加入group的請求,表示該consumer是該組的成員,Coordinator會接收到該請求,會給集羣分配一個Leader(通常是第一個),讓其負責partition的分配
  3. 發送SGR請求:JGR請求成功後,如果發現當前Consumer是leader,那麼會進行partition的分配,併發起SGR請求將分配結果發送給Coordinator;如果不是leader,那麼也會發起SGR請求,不過分配結果爲空

問題7.2: Rebalance有什麼影響

Rebalance本身是Kafka集羣的一個保護設定,用於剔除掉無法消費或者過慢的消費者,然後由於我們的數據量較大,同時後續消費後的數據寫入需要走網絡IO,很有可能存在依賴的第三方服務存在慢的情況而導致我們超時。
Rebalance對我們數據的影響主要有以下幾點:

  1. 數據重複消費: 消費過的數據由於提交offset任務也會失敗,在partition被分配給其他消費者的時候,會造成重複消費,數據重複且增加集羣壓力
  2. Rebalance擴散到整個ConsumerGroup的所有消費者,因爲一個消費者的退出,導致整個Group進行了Rebalance,並在一個比較慢的時間內達到穩定狀態,影響面較大
  3. 頻繁的Rebalance反而降低了消息的消費速度,大部分時間都在重複消費和Rebalance
  4. 數據不能及時消費,會累積lag,在Kafka的TTL之後會丟棄數據
    上面的影響對於我們系統來說,都是致命的。

問題7.3:怎麼解決rebalance中遇到的問題呢?

要避免 Rebalance,還是要從 Rebalance 發生的時機入手。我們在前面說過,Rebalance 主要發生的時機有三個:

  • 組成員數量發生變化
  • 訂閱主題數量發生變化
  • 訂閱主題的分區數發生變化

後兩個我們大可以人爲的避免,發生rebalance最常見的原因是消費組成員的變化。

消費者成員正常的添加和停掉導致rebalance,這種情況無法避免,但是時在某些情況下,Consumer 實例會被 Coordinator 錯誤地認爲 “已停止” 從而被“踢出”Group。從而導致rebalance。

當 Consumer Group 完成 Rebalance 之後,每個 Consumer 實例都會定期地向 Coordinator 發送心跳請求,表明它還存活着。如果某個 Consumer 實例不能及時地發送這些心跳請求,Coordinator 就會認爲該 Consumer 已經 “死” 了,從而將其從 Group 中移除,然後開啓新一輪 Rebalance。這個時間可以通過Consumer 端的參數 session.timeout.ms進行配置。默認值是 10 秒。

除了這個參數,Consumer 還提供了一個控制發送心跳請求頻率的參數,就是 heartbeat.interval.ms。這個值設置得越小,Consumer 實例發送心跳請求的頻率就越高。頻繁地發送心跳請求會額外消耗帶寬資源,但好處是能夠更加快速地知曉當前是否開啓 Rebalance,因爲,目前 Coordinator 通知各個 Consumer 實例開啓 Rebalance 的方法,就是將 REBALANCE_NEEDED 標誌封裝進心跳請求的響應體中。

除了以上兩個參數,Consumer 端還有一個參數,用於控制 Consumer 實際消費能力對 Rebalance 的影響,即 max.poll.interval.ms 參數。它限定了 Consumer 端應用程序兩次調用 poll 方法的最大時間間隔。它的默認值是 5 分鐘,表示你的 Consumer 程序如果在 5 分鐘之內無法消費完 poll 方法返回的消息,那麼 Consumer 會主動發起 “離開組” 的請求,Coordinator 也會開啓新一輪 Rebalance。

通過上面的分析,我們可以看一下那些rebalance是可以避免的:

第一類非必要 Rebalance 是因爲未能及時發送心跳,導致 Consumer 被 “踢出”Group 而引發的。這種情況下我們可以設置 session.timeout.ms 和 heartbeat.interval.ms 的值,來儘量避免rebalance的出現。(以下的配置是在網上找到的最佳實踐,暫時還沒測試過)

設置 session.timeout.ms = 6s。
設置 heartbeat.interval.ms = 2s。
要保證 Consumer 實例在被判定爲 “dead” 之前,能夠發送至少 3 輪的心跳請求,即 session.timeout.ms >= 3 * heartbeat.interval.ms。
將 session.timeout.ms 設置成 6s 主要是爲了讓 Coordinator 能夠更快地定位已經掛掉的 Consumer,早日把它們踢出 Group。

第二類非必要 Rebalance 是 Consumer 消費時間過長導致的。此時,max.poll.interval.ms 參數值的設置顯得尤爲關鍵。如果要避免非預期的 Rebalance,你最好將該參數值設置得大一點,比你的下游最大處理時間稍長一點。

總之,要爲業務處理邏輯留下充足的時間。這樣,Consumer 就不會因爲處理這些消息的時間太長而引發 Rebalance 。

問題7.4:kafka一次reblance大概要多久

1個Topic,10個partition,3個consumer
測試結果
經過幾輪測試發現每次rebalance所消耗的時間大概在 80ms~100ms平均耗時在87ms左右。

問題8:如何保證kafka順序消費

這個在我看來是一個僞命題,如果要保證順序消費爲啥要用kafka呢,只是需要做到異步或者解耦?
如果一定要做到順序消費,肯定是可以的,但是這個浪費資源,因爲kafka就是針對高併發大吞吐量而生,下面說一下順序消費方案:
1、一個toppic、一個partition、一個線程
2、一個topic、n個partition、n個線程,這裏生產時需要根據需求將需要排序的數據發送到指定的message key

問題9:kafka爲何這麼快

Kafka 實現了零拷貝原理來快速移動數據,避免了內核之間的切換。Kafka 可以將數據記錄分批發送,從生產者到文件系統(Kafka 主題日誌)到消費者,可以端到端的查看這些批次的數據。批處理能夠進行更有效的數據壓縮並減少 I/O 延遲,Kafka 採取順序寫入磁盤的方式,避免了隨機磁盤尋址的浪費,更多關於磁盤尋址的瞭解,請參閱 程序員需要了解的硬核知識之磁盤 。
總結一下其實就是四個要點

  • 順序讀寫
  • 零拷貝
  • 消息壓縮
  • 分批發送
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章