Kafka的10道基礎(chǔ)面試題
1. Kafka是什么?
Kafka起初是一個(gè)多分區(qū)、多副本且基于ZooKeeper協(xié)調(diào)的分布式消息系統(tǒng),現(xiàn)已被定位為一個(gè)分布式流式處理平臺。
2. Kafka的架構(gòu)了解嗎?
建議按以下順序講述:
Kafka是基于發(fā)布/訂閱的消息系統(tǒng)(引出Producer、Consumer和Broker),所以存在三個(gè)角色Producer(生產(chǎn)消息)、Broker(Kafka實(shí)例)和Consumer(消費(fèi)消息)。
生產(chǎn)者會將消息推送到Kafka的某個(gè)Topic上,以此區(qū)分消息。
為了高可用性,通過在集群上部署多個(gè)Broker,一個(gè)Topic將以多副本的形式分布在多個(gè)Broker上,基于ZK選出一個(gè)Leader副本,而其他Follower副本則負(fù)責(zé)同步Leader副本,避免單點(diǎn)問題。
為了高吞吐量,再將Topic劃分成多個(gè)分區(qū),可讓Topic的吞吐量不受單機(jī)限制。
為了高吞吐量,對于多個(gè)分區(qū),單個(gè)消費(fèi)者也可變成多個(gè),形成消費(fèi)組,一個(gè)分區(qū)由一個(gè)消費(fèi)者負(fù)責(zé)。

3. 了解其他MQ嗎?有什么不同?
有了解RadbbitMQ,RabbitMQ由于有消息確認(rèn)機(jī)制,所以數(shù)據(jù)丟失的可能性更小,適合嚴(yán)格的金融場景。
而Kafka的優(yōu)勢則在于其吞吐量更大,適合處理活躍的流式數(shù)據(jù)。
4. 如何保證消息的有序性?
Kafka只能保證局部有序,即只能保證一個(gè)分區(qū)里的消息有序。而其具體實(shí)現(xiàn)是通過生產(chǎn)者為每個(gè)分區(qū)的消息維護(hù)一個(gè)發(fā)送隊(duì)列,我們需要將保證順序的消息都發(fā)送到同一個(gè)分區(qū)中。并且由于Kafka會同時(shí)發(fā)送多個(gè)消息,所以還需指定max.in.flight.requests.per.connection為1,保證前一個(gè)消息發(fā)送成功,后一個(gè)消息才開始發(fā)送。
max.in.flight>1 時(shí)能保證有序性嗎?
可以,設(shè)置冪等能保證。不過max.in.flight不能大于5。這是因?yàn)锽roker端只會緩存最近5個(gè)Batch的SequenceNumber,例如我們發(fā)送1到6的報(bào)文,其中1發(fā)送失敗,2-5發(fā)送成功,Broker緩存下來,當(dāng)1重試時(shí),Broker檢查到1小于緩存中的最小序號,會拋出異常,而Producer將重試發(fā)送1超過最多次數(shù)或超時(shí),影響性能。
冪等如何保證有序性?
通過引入ProduceID(PID)和SequenceNumber的概念,每個(gè)Producer在初始化時(shí)被分配唯一的PID,而<Topic,Partition>的每條有一個(gè)從0單調(diào)遞增的SequenceNumber。在發(fā)送消息時(shí),由以下三點(diǎn)保證:
驗(yàn)證序號連續(xù):Broker會驗(yàn)證Batch的SequenceNumber是否連續(xù),若不連續(xù),拋出異常;
重試時(shí),batch放置正確位置:Producer請求重試時(shí),會根據(jù)SequenceNumber將Batch放在隊(duì)列中的合適位置;
重試時(shí),max.in.flight調(diào)為1:當(dāng)請求重試時(shí),會把max.in.flight動態(tài)調(diào)整為1,保證請求序號小的先發(fā)送成功。
5. 如何保證冪等?
Kafka具有冪等機(jī)制,但默認(rèn)不開啟,需要設(shè)置enable.idempotence為true開啟。但只能實(shí)現(xiàn)單會話、單分區(qū)上的冪等。
為什么只能實(shí)現(xiàn)單會話上的冪等?
在Producer初始化時(shí),Kafka會為其重新分配一個(gè)新的PID,而Broker端在維護(hù)SequenceNumber時(shí)是以<ProducerID, Topic, Partition>作為維度,因此當(dāng)PID變化時(shí)Broker將無法獲得之前的狀態(tài)信息,無法做到單會話上的不丟不沖。
如何實(shí)現(xiàn)跨會話冪等?
事務(wù)機(jī)制,通過引入TransactionID和Epoch。不同于PID是由內(nèi)部進(jìn)行分配,TrasactionID是由用戶提供。而TransactionID與PID會一一對應(yīng),這樣當(dāng)Producer宕機(jī)時(shí),集群啟動一個(gè)新的Producer,在初始化時(shí)可以通過TransactionID獲得PID,便能繼續(xù)工作。同時(shí)會被分配一個(gè)單調(diào)遞增的Epoch,來保證當(dāng)舊Producer恢復(fù)后可能生產(chǎn)出重復(fù)消息,Broker段會拒絕舊Epoch的消息。
6. 支持什么語義?
三種語義:
最多一次(At Most Once):不會重復(fù)發(fā)送,可能消息丟失
最少一次(At Least Once):會重復(fù)發(fā)送,消息不會丟失(默認(rèn))
只有一次(Exactly Once):不會重復(fù)發(fā)送,消息不會丟失
7. 如何保證Exactly Once語義?
Producer冪等 + At Least Once = Exactly Once(單分區(qū)、單會話)
事務(wù)可實(shí)現(xiàn)跨分區(qū)、跨會話的Exactly Once語義
8. 消息重復(fù)的場景有哪些?如何解決?
Broker在寫入消息后,Producer沒有收到成功的響應(yīng)。
解決方法:
啟動冪等;
acks = 0,不重試,但會丟失消息。
9. 消息丟失的場景有哪些?如何解決?
(一)Producer端丟失消息
在調(diào)用send方法時(shí),由于網(wǎng)絡(luò)原因發(fā)送失敗。
解決辦法:設(shè)置retries為一個(gè)合適的值,一般為3,此外重試的間隔不能太小,避免網(wǎng)絡(luò)一次波動的區(qū)間就把三次重試用完了。
(二)Consumer端丟失消息
自動提交offset時(shí),可能未來得及處理消息,但offset已被提交。
解決辦法:關(guān)閉自動提交,消費(fèi)完后手動提交offset。
(三)Broker端丟失消息
Leader副本所在的Broker宕機(jī),而Follower副本還沒有完全通過Leader
解決辦法:
設(shè)置acks =-1或ALL,保證Follower副本寫入消息;
replication.factor > 3,保證分區(qū)至少有3個(gè)副本,冗余消息;
min.insync.replicas >1,消息至少被寫入2個(gè)副本才認(rèn)為成功;
unclean.leader.election.enable=false,避免從非ISR中選舉Leader。
10. Kafka吞吐量高的原因
順序?qū)?/strong>:寫讀數(shù)據(jù)時(shí),數(shù)據(jù)直接追加在文件的末尾;
MMAP:數(shù)據(jù)不實(shí)時(shí)寫入硬盤,以此提高IO效率;
零拷貝:讀數(shù)據(jù)時(shí),使用了sendfile,磁盤文件讀到OS內(nèi)核緩沖區(qū)后,直接轉(zhuǎn)到socket buffer進(jìn)行網(wǎng)絡(luò)發(fā)送;
批量壓縮:消耗少量的CPU資源,提高IO效率;
一句話貫穿:Kafka把所有的消息都變成一個(gè)個(gè)批量的文件,并且進(jìn)行合理的批量壓縮,減少網(wǎng)絡(luò)IO的損耗,寫入是通過MMAP提高IO效率,同時(shí)由于單個(gè)分區(qū)是順序?qū)懳募?,所以速度最?yōu);讀取數(shù)據(jù)的時(shí)候配合sendfile直接暴力輸出。
參考資料
Kafka 面試題:基礎(chǔ) 27 問,必須都會的呀: https://xie.infoq.cn/article/6c879c4c3b52e416f251b2909
[2]八年面試生涯,整理了一套Kafka面試題: https://juejin.cn/post/6844903889003610119
[3]32 道常見的 Kafka 面試題你都會嗎?附答案: https://www.iteblog.com/archives/2605.html
[4]Kafka面試題與答案全套整理: http://trumandu.github.io/2019/04/13/Kafka%E9%9D%A2%E8%AF%95%E9%A2%98%E4%B8%8E%E7%AD%94%E6%A1%88%E5%85%A8%E5%A5%97%E6%95%B4%E7%90%86/
[5]大數(shù)據(jù)Kafka面試題: https://zhuanlan.zhihu.com/p/107350990
[6]面試官問我如何保證Kafka不丟失消息?我哭了: https://juejin.cn/post/6844904094021189639
[7]Kafka速度快的原因: https://www.linuxidc.com/Linux/2019-11/161504.htm
[8]萬字長文干貨 | Kafka 事務(wù)性之冪等性實(shí)現(xiàn): https://cloud.tencent.com/developer/article/1430049
[9]Kafka事務(wù)特性詳解: https://www.jianshu.com/p/64c93065473e
有道無術(shù),術(shù)可成;有術(shù)無道,止于術(shù)
歡迎大家關(guān)注Java之道公眾號
好文章,我在看??
