9 個 Kafka 面試題,你會幾個?

Java技術棧
www.javastack.cn
關注閱讀更多優(yōu)質(zhì)文章
作者:lipengxs
地址:my.oschina.net/lipengxs/blog/4312141
問題1:消息隊列的作用
1、 解耦
快遞小哥手上有很多快遞需要送,他每次都需要先電話一一確認收貨人是否有空、哪個時間段有空,然后再確定好送貨的方案。這樣完全依賴收貨人了!如果快遞一多,快遞小哥估計的忙瘋了……
如果有了便利店,快遞小哥只需要將同一個小區(qū)的快遞放在同一個便利店,然后通知收貨人來取貨就可以了,這時候快遞小哥和收貨人就實現(xiàn)了解耦!
2、 異步
快遞小哥打電話給我后需要一直在你樓下等著,直到我拿走你的快遞他才能去送其他人的。快遞小哥將快遞放在小芳便利店后,又可以干其他的活兒去了,不需要等待你到來而一直處于等待狀態(tài)。提高了工作的效率。
3、 削峰
假設雙十一我買了不同店里的各種商品,而恰巧這些店發(fā)貨的快遞都不一樣,有中通、圓通、申通、各種通等……
更巧的是他們都同時到貨了!中通的小哥打來電話叫我去北門取快遞、圓通小哥叫我去南門、申通小哥叫我去東門。我一時手忙腳亂……
我們能看到在系統(tǒng)需要交互的場景中,使用消息隊列中間件真的是好處多多,基于這種思路,就有了豐巢、菜鳥驛站等比小芳便利店更專業(yè)的“中間件”了。
問題2:Kafka中有哪幾個組件?
生產(chǎn)者:在Kafka,生產(chǎn)者發(fā)布通信以及向Kafka主題發(fā)布消息。
消費者:Kafka消費者訂閱了一個主題,并且還從主題中讀取和處理消息。
經(jīng)紀人:在管理主題中的消息存儲時,我們使用Kafka Brokers。?
Kafka系統(tǒng)架構(gòu)
問題3:簡單說一下ack機制
ack:producer收到多少broker的答復才算真的發(fā)送成功
0表示producer無需等待leader的確認(吞吐最高、數(shù)據(jù)可靠性最差)
1代表需要leader確認寫入它的本地log并立即確認
-1/all 代表所有的ISR都完成后確認(吞吐最低、數(shù)據(jù)可靠性最高)
問題4:Kafka 如何判斷節(jié)點是否存活
(1)節(jié)點必須可以維護和 ZooKeeper 的連接,ZooKeeper 通過心跳機制檢查每個節(jié)點的連 接
(2)如果節(jié)點是個 follower,他必須能及時的同步 leader 的寫操作,延時不能太久
問題5:Kafka 消息是采用 Pull 模式,還是 Push 模式
Kafka 最初考慮的問題是,customer 應該從 brokes 拉取消息還是 brokers 將消息推送到 consumer,也就是 pull 還 push。
在這方面,Kafka 遵循了一種大部分消息系統(tǒng)共同的傳統(tǒng) 的設計:producer 將消息推送到 broker,consumer 從 broker 拉取消息 一些消息系統(tǒng)比如 Scribe 和 Apache Flume 采用了 push 模式,將消息推送到下游的 consumer。
這樣做有好處也有壞處:由 broker 決定消息推送的速率,對于不同消費速率的 consumer 就不太好處理了。
消息系統(tǒng)都致力于讓 consumer 以最大的速率最快速的消費消 息,但不幸的是,push 模式下,當 broker 推送的速率遠大于 consumer 消費的速率時, consumer 恐怕就要崩潰了。
最終 Kafka 還是選取了傳統(tǒng)的 pull 模式 Pull 模式的另外一個好處是 consumer 可以自主決定是否批量的從 broker 拉取數(shù)據(jù)。Push 模式必須在不知道下游 consumer 消費能力和消費策略的情況下決定是立即推送每條消息還 是緩存之后批量推送。
如果為了避免 consumer 崩潰而采用較低的推送速率,將可能導致一 次只推送較少的消息而造成浪費。
Pull 模式下,consumer 就可以根據(jù)自己的消費能力去決 定這些策略 Pull 有個缺點是,如果 broker 沒有可供消費的消息,將導致 consumer 不斷在循環(huán)中輪詢, 直到新消息到 t 達。為了避免這點,Kafka 有個參數(shù)可以讓 consumer 阻塞知道新消息到達 (當然也可以阻塞知道消息的數(shù)量達到某個特定的量這樣就可以批量發(fā))
問題6 能說一下leader選舉過程嗎
我們知道ZooKeeper集群中也有選舉機制,是通過Paxos算法,通過不同節(jié)點向其他節(jié)點發(fā)送信息來投票選舉出leader,但是Kafka的leader的選舉就沒有這么復雜了。
關注公眾號Java技術棧回復面試可以獲取更多Java技術系列面試題。
問題7:kafka什么情況下會rebalance
rebalance 的觸發(fā)條件有五個。
條件1:有新的consumer加入
條件2:舊的consumer掛了
條件3:coordinator掛了,集群選舉出新的coordinator
條件4:topic的partition新加
條件5:consumer調(diào)用unsubscrible(),取消topic的訂閱
rebalance 發(fā)生時,Group 下所有 consumer 實例都會協(xié)調(diào)在一起共同參與,kafka 能夠保證盡量達到最公平的分配。但是 Rebalance 過程對 consumer group 會造成比較嚴重的影響。在 Rebalance 的過程中 consumer group 下的所有消費者實例都會停止工作,等待 Rebalance 過程完成。
關注公眾號Java技術棧回復面試可以獲取更多Java技術系列面試題。
問題7.1:能簡單說一下rebalance過程嗎?
主要的流程如下:
發(fā)送GCR請求尋找Coordinator:這個過程主要會向集群中負載最小的broker發(fā)起請求,等待成功返回后,那么該Broker將作為Coordinator,嘗試連接該Coordinator
發(fā)送JGR請求加入該組:當成功找到Coordinator后,那么就要發(fā)起加入group的請求,表示該consumer是該組的成員,Coordinator會接收到該請求,會給集群分配一個Leader(通常是第一個),讓其負責partition的分配
發(fā)送SGR請求:JGR請求成功后,如果發(fā)現(xiàn)當前Consumer是leader,那么會進行partition的分配,并發(fā)起SGR請求將分配結(jié)果發(fā)送給Coordinator;如果不是leader,那么也會發(fā)起SGR請求,不過分配結(jié)果為空
問題7.2:Rebalance有什么影響
Rebalance本身是Kafka集群的一個保護設定,用于剔除掉無法消費或者過慢的消費者,然后由于我們的數(shù)據(jù)量較大,同時后續(xù)消費后的數(shù)據(jù)寫入需要走網(wǎng)絡IO,很有可能存在依賴的第三方服務存在慢的情況而導致我們超時。Rebalance對我們數(shù)據(jù)的影響主要有以下幾點:
數(shù)據(jù)重復消費: 消費過的數(shù)據(jù)由于提交offset任務也會失敗,在partition被分配給其他消費者的時候,會造成重復消費,數(shù)據(jù)重復且增加集群壓力
Rebalance擴散到整個ConsumerGroup的所有消費者,因為一個消費者的退出,導致整個Group進行了Rebalance,并在一個比較慢的時間內(nèi)達到穩(wěn)定狀態(tài),影響面較大
頻繁的Rebalance反而降低了消息的消費速度,大部分時間都在重復消費和Rebalance
數(shù)據(jù)不能及時消費,會累積lag,在Kafka的TTL之后會丟棄數(shù)據(jù) 上面的影響對于我們系統(tǒng)來說,都是致命的。
問題7.3:怎么解決rebalance中遇到的問題呢?
要避免 Rebalance,還是要從 Rebalance 發(fā)生的時機入手。我們在前面說過,Rebalance 主要發(fā)生的時機有三個:
組成員數(shù)量發(fā)生變化
訂閱主題數(shù)量發(fā)生變化
訂閱主題的分區(qū)數(shù)發(fā)生變化
后兩個我們大可以人為的避免,發(fā)生rebalance最常見的原因是消費組成員的變化。
消費者成員正常的添加和停掉導致rebalance,這種情況無法避免,但是時在某些情況下,Consumer 實例會被 Coordinator 錯誤地認為 “已停止” 從而被“踢出”Group。從而導致rebalance。
當 Consumer Group 完成 Rebalance 之后,每個 Consumer 實例都會定期地向 Coordinator 發(fā)送心跳請求,表明它還存活著。如果某個 Consumer 實例不能及時地發(fā)送這些心跳請求,Coordinator 就會認為該 Consumer 已經(jīng) “死” 了,從而將其從 Group 中移除,然后開啟新一輪 Rebalance。這個時間可以通過Consumer 端的參數(shù) session.timeout.ms進行配置。默認值是 10 秒。
除了這個參數(shù),Consumer 還提供了一個控制發(fā)送心跳請求頻率的參數(shù),就是 heartbeat.interval.ms。這個值設置得越小,Consumer 實例發(fā)送心跳請求的頻率就越高。頻繁地發(fā)送心跳請求會額外消耗帶寬資源,但好處是能夠更加快速地知曉當前是否開啟 Rebalance,因為,目前 Coordinator 通知各個 Consumer 實例開啟 Rebalance 的方法,就是將 REBALANCE_NEEDED 標志封裝進心跳請求的響應體中。
除了以上兩個參數(shù),Consumer 端還有一個參數(shù),用于控制 Consumer 實際消費能力對 Rebalance 的影響,即 max.poll.interval.ms 參數(shù)。它限定了 Consumer 端應用程序兩次調(diào)用 poll 方法的最大時間間隔。它的默認值是 5 分鐘,表示你的 Consumer 程序如果在 5 分鐘之內(nèi)無法消費完 poll 方法返回的消息,那么 Consumer 會主動發(fā)起 “離開組” 的請求,Coordinator 也會開啟新一輪 Rebalance。
通過上面的分析,我們可以看一下那些rebalance是可以避免的:
第一類非必要 Rebalance 是因為未能及時發(fā)送心跳,導致 Consumer 被 “踢出”Group 而引發(fā)的。這種情況下我們可以設置 session.timeout.ms 和 heartbeat.interval.ms 的值,來盡量避免rebalance的出現(xiàn)。(以下的配置是在網(wǎng)上找到的最佳實踐,暫時還沒測試過)
設置 session.timeout.ms = 6s。設置 heartbeat.interval.ms = 2s。要保證 Consumer 實例在被判定為 “dead” 之前,能夠發(fā)送至少 3 輪的心跳請求,即 session.timeout.ms >= 3 * heartbeat.interval.ms。將 session.timeout.ms 設置成 6s 主要是為了讓 Coordinator 能夠更快地定位已經(jīng)掛掉的 Consumer,早日把它們踢出 Group。
第二類非必要 Rebalance 是 Consumer 消費時間過長導致的。此時,max.poll.interval.ms 參數(shù)值的設置顯得尤為關鍵。如果要避免非預期的 Rebalance,你最好將該參數(shù)值設置得大一點,比你的下游最大處理時間稍長一點。
總之,要為業(yè)務處理邏輯留下充足的時間。這樣,Consumer 就不會因為處理這些消息的時間太長而引發(fā) Rebalance 。
問題7.4:kafka一次reblance大概要多久
1個Topic,10個partition,3個consumer 測試結(jié)果 經(jīng)過幾輪測試發(fā)現(xiàn)每次rebalance所消耗的時間大概在 80ms~100ms平均耗時在87ms左右。
問題8:如何保證kafka順序消費
這個在我看來是一個偽命題,如果要保證順序消費為啥要用kafka呢,只是需要做到異步或者解耦?如果一定要做到順序消費,肯定是可以的,但是這個浪費資源,因為kafka就是針對高并發(fā)大吞吐量而生,下面說一下順序消費方案:1、一個topic、一個partition、一個線程 2、一個topic、n個partition、n個線程,這里生產(chǎn)時需要根據(jù)需求將需要排序的數(shù)據(jù)發(fā)送到指定的message key
問題9:kafka為何這么快
批處理能夠進行更有效的數(shù)據(jù)壓縮并減少 I/O 延遲,Kafka 采取順序?qū)懭氪疟P的方式,避免了隨機磁盤尋址的浪費,更多關于磁盤尋址的了解,請參閱 程序員需要了解的硬核知識之磁盤 。總結(jié)一下其實就是四個要點
順序讀寫
零拷貝
消息壓縮
分批發(fā)送
最后,關注公眾號Java技術棧回復面試可以獲取更多Java技術系列面試題。





關注Java技術棧看更多干貨


