kafka删除队列_没想到 Kafka 还会这样问,学会这些带你轻松搞定大厂面试!
一、前言
自上次師兄遭受了面試官 「Kafka」 的暴擊追問后,回來發奮圖強,企圖“「吊打面試官」”,奈何還是面試官套路深啊,最近的面試,又被問到「知識盲點」了!讓我們一起來看看,可憐的師兄又遇到了哪些讓人頭禿的問題 {{{(>_
二、面試題
常用的消息隊列有哪些 ? 為何使用消息隊列 ? Kafka與傳統的消息隊列服務有什么不同?
?Kafka的讀寫流程
Kafka的文件結構 broker存儲數據有哪些?Kafka怎么保證partition的偏移量?follower參加讀寫嗎?Kafka為什么只讓leader進行讀寫?如果讓follower也可以讀寫,會怎么樣?
Kafak是怎么實現對offset的索引 ack設為1的時候,producer生產數據時候,leader接受到數據,返回ack之后,leader宕機了,那么數據是否就丟失了?ack配置成-1是不是數據一定會進磁盤?是不是不管怎么是設置ack還是有概率丟失消息?
?簡要描述Kafak數據高可用的原理是什么 一個topic三個broker一個leader,leader所在的broker掛了,選舉原則是什么?Kafka api low-level與high-level有什么區別,使用low-level api需要處理哪些細節?
??以上,「便是和師兄聊到了一些他踩坑的面試題和一些同類型的面試題」,我進行了整理。說實話,如果不深入的了解Kafak,我想小伙伴們在面試時多半是要踩雷的,當然也包括我!(ノへ ̄、) 所以,為了避免被面試官瘋狂吊打,我們還做好充分準備,不求”翻身做主“,但求旗鼓相當,那樣Offer輕松到手豈不妙哉!
?三、思路
還是和上一篇博客一樣 師兄大廠面試遇到面試官的 Kafka 暴擊三連問,快面哭了!我個人建議,大家最好先搭建一個技術棧完整的知識框架,這樣在面試時就能做到無懈可擊啦!
四、關于消息隊列
4.1 Kafka創建背景
Kafka是一個消息系統,原本開發自LinkedIn,用作LinkedIn的活動流(Activity Stream)和運營數據處理管道(Pipeline)的基礎。現在它已被多家不同類型的公司「作為多種類型的數據管道和消息系統」使用。
「活動流數據」是幾乎所有站點在對其網站使用情況做報表時都要用到的數據中最常規的部分。「這種數據通常的處理方式是先把各種活動以日志的形式寫入某種文件,然后周期性地對這些文件進行統計分析」。近年來,活動和運營數據處理已經成為了網站軟件產品特性中一個至關重要的組成部分,這就需要一套稍微更加復雜的基礎設施對其提供支持,Kafka也就應運而生。
4.2 為何使用消息隊列
「解耦」在項目啟動之初來預測將來項目會碰到什么需求,是極其困難的。消息系統在處理過程中間插入了一個隱含的、基于數據的接口層,兩邊的處理過程都要實現這一接口。這允許你獨立的擴展或修改兩邊的處理過程,只要確保它們遵守同樣的接口約束。
「冗余」有些情況下,處理數據的過程會失敗。除非數據被持久化,否則將造成丟失。消息隊列把數據進行持久化直到它們已經被完全處理,通過這一方式規避了數據丟失風險。許多消息隊列所采用的“插入-獲取-刪除”范式中,在把一個消息從隊列中刪除之前,需要你的處理系統明確的指出該消息已經被處理完畢,從而確保你的數據被安全的保存直到你使用完畢。
「擴展性」因為消息隊列解耦了你的處理過程,所以增大消息入隊和處理的頻率是很容易的,只要另外增加處理過程即可。不需要改變代碼、不需要調節參數。擴展就像調大電力按鈕一樣簡單。
「靈活性 & 峰值處理能力」在訪問量劇增的情況下,應用仍然需要繼續發揮作用,但是這樣的突發流量并不常見;如果為以能處理這類峰值訪問為標準來投入資源隨時待命無疑是巨大的浪費。使用消息隊列能夠使關鍵組件頂住突發的訪問壓力,而不會因為突發的超負荷的請求而完全崩潰。
「可恢復性」系統的一部分組件失效時,不會影響到整個系統。消息隊列降低了進程間的耦合度,所以即使一個處理消息的進程掛掉,加入隊列中的消息仍然可以在系統恢復后被處理。
「順序保證」在大多使用場景下,數據處理的順序都很重要。大部分消息隊列本來就是排序的,并且能保證數據會按照特定的順序來處理。Kafka保證一個Partition內的消息的有序性。
「緩沖」在任何重要的系統中,都會有需要不同的處理時間的元素。例如,加載一張圖片比應用過濾器花費更少的時間。消息隊列通過一個緩沖層來幫助任務最高效率的執行———寫入隊列的處理會盡可能的快速。該緩沖有助于控制和優化數據流經過系統的速度。
「異步通信」很多時候,用戶不想也不需要立即處理消息。消息隊列提供了異步處理機制,允許用戶把一個消息放入隊列,但并不立即處理它。想向隊列中放入多少消息就放多少,然后在需要的時候再去處理它們。
4.3 和常用消息隊列的對比
「RabbitMQ」RabbitMQ是使用Erlang編寫的一個開源的消息隊列,本身支持很多的協議:AMQP,XMPP, SMTP, STOMP,也正因如此,它非常重量級,更適合于企業級的開發。同時實現了Broker構架,這意味著消息在發送給客戶端時先在中心隊列排隊。對路由,負載均衡或者數據持久化都有很好的支持。
「Redis」Redis是一個基于Key-Value對的NoSQL數據庫,開發維護很活躍。雖然它是一個Key-Value數據庫存儲系統,但它本身支持MQ功能,所以完全可以當做一個輕量級的隊列服務來使用。對于RabbitMQ和Redis的入隊和出隊操作,各執行100萬次,每10萬次記錄一次執行時間。測試數據分為128Bytes、512Bytes、1K和10K四個不同大小的數據。實驗表明:入隊時,當數據比較小時Redis的性能要高于RabbitMQ,而如果數據大小超過了10K,Redis則慢的無法忍受;出隊時,無論數據大小,Redis都表現出非常好的性能,而RabbitMQ的出隊性能則遠低于Redis。
「ZeroMQ」ZeroMQ號稱最快的消息隊列系統,尤其針對大吞吐量的需求場景。ZMQ能夠實現RabbitMQ不擅長的高級/復雜的隊列,但是開發人員需要自己組合多種技術框架,技術上的復雜度是對這MQ能夠應用成功的挑戰。ZeroMQ具有一個獨特的非中間件的模式,你不需要安裝和運行一個消息服務器或中間件,因為你的應用程序將扮演這個服務器角色。你只需要簡單的引用ZeroMQ程序庫,可以使用NuGet安裝,然后你就可以愉快的在應用程序之間發送消息了。但是ZeroMQ僅提供非持久性的隊列,也就是說如果宕機,數據將會丟失。其中,Twitter的Storm 0.9.0以前的版本中默認使用ZeroMQ作為數據流的傳輸(Storm從0.9版本開始同時支持ZeroMQ和Netty作為傳輸模塊)。
「ActiveMQ」ActiveMQ是Apache下的一個子項目。類似于ZeroMQ,它能夠以代理人和點對點的技術實現隊列。同時類似于RabbitMQ,它少量代碼就可以高效地實現高級應用場景。
「Kafka/Jafka」Kafka是Apache下的一個子項目,是一個高性能跨語言分布式發布/訂閱消息隊列系統,而Jafka是在Kafka之上孵化而來的,即Kafka的一個升級版。具有以下特性:快速持久化,可以在O(1)的系統開銷下進行消息持久化;高吞吐,在一臺普通的服務器上既可以達到10W/s的吞吐速率;完全的分布式系統,Broker、Producer、Consumer都原生自動支持分布式,自動實現負載均衡;支持Hadoop數據并行加載,對于像Hadoop的一樣的日志數據和離線分析系統,但又要求實時處理的限制,這是一個可行的解決方案。Kafka通過Hadoop的并行加載機制統一了在線和離線的消息處理。Apache Kafka相對于ActiveMQ是一個非常輕量級的消息系統,除了性能非常好之外,還是一個工作良好的分布式系統。
4.4 總結
關于 Kafka 和傳統消息隊列有何不同,在上一篇文章中已經做出部分解答,這里我就不再贅述。「一般情況下,Kafka應用在大數據日志處理或對實時性(少量延遲),可靠性(少量丟數據)要求稍低的場景使用」。
五、關于Kafka存儲機制與讀寫流程
5.1 Kafka存儲機制
在Kafka 架構深入已經講明了這個問題,但這張圖的結構更易于理解,如下。
- 「Broker」:消息中間件處理結點,一個Kafka節點就是一個broker,多個broker可以組成一個Kafka集群。
- 「Topic」:一類消息,例如page view日志、click日志等都可以以topic的形式存在,Kafka集群能夠同時負責多個topic的分發。
- 「Partition」:topic物理上的分組,一個topic可以分為多個partition,每個partition是一個有序的隊列。
- 「Segment」:partition物理上由多個segment組成。
Kafka用topic對消息進行歸類,每一個topic可以分為多個分區,分區中的消息不重復,每個分區又有很多個segment(段),「segment是在磁盤上就是一對文件,包含index和log文件,兩種文件名相同,后綴不同」。
「每個topic的第一個segment的兩種文件都是00000000000000000000.index和00000000000000000000.log,后來新產生的文件名都以上一個segment中最后一條消息的offset(偏移量)結尾,不足20個字符的用0填充。」
「Tip:Kafka數據被消費后雖然不會被立即刪除,但不可能一直不刪除,Kafka根據兩個設置定時檢測做刪除操作」:
「滿足任何一個都會刪除之前的segment,記住不是刪除某一個消息,刪除的最小單位是segment。」
以上面的Segment文件為例,展示出Segment:00000000000000170410的index文件和log文件的對應的關系,如下圖:
如上圖,「index索引文件存儲大量的元數據,log數據文件存儲大量的消息,索引文件中的元數據指向對應數據文件中message的物理偏移地址。」
?「如何根據索引文件元數據定位數據位置?」
如:index索引文件元數據[3,348],在log數據文件中表示第3個消息,在全局partition中表示170410+3=170413個消息,該條消息在相應log文件中的物理偏移地址為348。
「那么如何從partition中通過offset查找message呢?」
如:讀取offset=170418的消息,查找segment文件,其中,
α. 00000000000000000000.index為最開始的文件,
β. 00000000000000170410.index(start offset=170410+1=170411),
γ. 00000000000000239430.index(start offset=239430+1=239431),
因此,定位offset=170418在00000000000000170410.index索引文件中。其他后續文件可以依次類推,以偏移量命名并排列這些文件,然后根據二分查找法就可以快速定位到具體文件位置。其次,根據00000000000000170410.index文件中的[8,1325]定位到00000000000000170410.log文件中的1325的位置進行讀取。
「那么怎么知道何時讀完本條消息,否則就讀到下一條消息的內容了?」
因為消息都具有固定的物理結構,包括:offset(8 Bytes)、消息體的大小(4 Bytes)、crc32(4 Bytes)、magic(1 Byte)、attributes(1 Byte)、key length(4 Bytes)、key(K Bytes)、payload(N Bytes)等等字段,可以確定一條消息的大小,即讀取到哪里截止。
5.2 讀寫流程
「寫流程:」
1.連接ZK集群,從ZK中拿到對應topic的partition信息和partition的Leader的相關信息
2.連接到對應Leader對應的broker
3.將消息發送到partition的Leader上
4.其他Follower從Leader上復制數據
5.依次返回ACK
6.直到所有ISR中的數據寫完成,才完成提交,整個寫過程結束
因為是描述寫流程,沒有將replica與ZK的心跳通訊表達出來,心跳通訊就是為了保證kafka高可用。一旦Leader掛了,或者Follower同步超時或者同步過慢,都會通過心跳將信息報告給ZK,由ZK做Leader選舉或者將Follower從ISR中移動到OSR中。
「讀流程:」
1.連接ZK集群,從ZK中拿到對應topic的partition信息和partition的Leader的相關信息
2.連接到對應Leader對應的broker
3.consumer將自己保存的offset發送給Leader
4.Leader根據offset等信息定位到segment(索引文件和日志文件)
5.根據索引文件中的內容,定位到日志文件中該偏移量對應的開始位置讀取相應長度的數據并返回給consumer
5.3 ?Kafka數據一致性
「數據一致性:Kafka是保存副本 leader讀寫,follower只備份;而 zookeeper是 leader讀寫,follower負責讀」 。
看到一位博主對 Kafka和Zookeeper 數據一致性 分析的很詳細,大家可以學習下,這里我參考了關于Kafka的部分。
「Kafka」,「只有leader 負責讀寫,follower只負責備份!!!」,「如果leader宕機的話,Kafaka動態維護了一個同步狀態的副本的集合(a set of in-sync replicas)」,簡稱「ISR」,「ISR中有f+1個節點,就可以允許在f個節點down掉的情況下不會丟失消息并正常提供服」。「ISR的成員是動態的,如果一個節點被淘汰了,當它重新達到“同步中”的狀態時,他可以重新加入ISR。因此如果leader宕了,直接從ISR中選擇一個follower就行。」
Kafka在引入Replication之后,同一個Partition可能會有多個Replica,而這時需要「在這些Replication之間選出一個Leader」,「Producer和Consumer只與這個Leader交互」,「其它Replica作為Follower從Leader中復制數據」。「因為需要保證同一個Partition的多個Replica之間的數據一致性(其中一個宕機后其它Replica必須要能繼續服務并且即不能造成數據重復也不能造成數據丟失)」。
如果沒有一個Leader,所有Replica都可同時讀/寫數據,那就需要保證多個Replica之間互相(N×N條通路)同步數據,數據的一致性和有序性非常難保證,「大大增加了Replication實現的復雜性,同時也增加了出現異常的幾率」。
而引入Leader后,只有Leader負責數據讀寫,Follower只向Leader順序Fetch數據(N條通路),系統更加簡單且高效。
「Kafka:由于Kafka的使用場景決定,其讀取數據時更關注數據的一致性。」
從leader讀取和寫入可以保證所有客戶端都得到相同的數據,否則可能存在一些在ISR中注冊的節點(replication-factor大于min.insync.replicas),因未來得及更新副本而無法提供的數據。相應的為了規避都從leader上讀取帶來的資源競爭,可以根據不同topic和不同partition設置不同的leader。
「如下所示:leader==>負責讀寫,follower 負責同步,只負責備份。」
六、關于kafka數據可靠性的保證
為保證 producer 發送的數據,能可靠的發送到指定的 topic,topic 的每個 partition 收到 producer 發送的數據后,都需要向 producer 發送 ack(acknowledgement 確認收到),如果 producer 收到 ack,就會進行下一輪的發送,否則重新發送數據。
6.1 副本數據同步策略
Kafka 選擇了第二種方案,原因如下:
6.2 ISR集合
采用第二種方案之后,設想以下情景:leader 收到數據,所有 follower 都開始同步數據,但有一個 follower,因為某種故障,遲遲不能與 leader 進行同步,那 leader 就要一直等下去,直到它完成同步,才能發送 ack。這個問題怎么解決呢?
Leader 維護了一個動態的 in-sync replica set (ISR),意為和 leader 保持同步的 follower 集合。當 ISR 中的 follower 完成數據的同步之后,leader 就會給 follower 發送 ack。如果 follower長時間 未 向 leader 同 步 數 據 , 則 該 follower 將 被 踢 出 ISR , 該 時 間 閾 值 由replica.lag.time.max.ms 參數設定。Leader 發生故障之后,就會從 ISR 中選舉新的 leader。
6.3 ACK應答機制
對于某些不太重要的數據,對數據的可靠性要求不是很高,能夠容忍數據的少量丟失,所以沒必要等 ISR 中的 follower 全部接收成功。
所以 Kafka 為用戶提供了三種可靠性級別,用戶根據對可靠性和延遲的要求進行權衡,選擇以下的配置。
「acks 參數配置:」
「0」:producer 不等待 broker 的 ack,這一操作提供了一個最低的延遲,broker 一接收到還沒有寫入磁盤就已經返回,當 broker 故障時有可能丟失數據;
「1」:producer 等待 broker 的 ack,partition 的 leader 落盤成功后返回 ack,「如果在 follower同步成功之前 leader 故障,那么將會丟失數據」;
「-1(all)」:producer 等待 broker 的 ack,partition 的 leader 和 follower 全部落盤成功后才返回 ack。「但是如果在 follower 同步完成后,broker 發送 ack 之前,leader 發生故障,那么會造成數據重復」。
6.4 故障處理細節
「LEO:指的是每個副本最大的 offset;HW:指的是消費者能見到的最大的 offset,ISR 隊列中最小的 LEO。」
(1)follower 故障 follower 發生故障后會被臨時踢出 ISR,待該 follower 恢復后,follower 會讀取本地磁盤記錄的上次的 HW,并將 log 文件高于 HW 的部分截取掉,從 HW 開始向 leader 進行同步。等該 follower 的 LEO 大于等于該 Partition 的 HW,即 follower 追上 leader 之后,就可以重新加入 ISR 了。
(2)leader 故障 leader 發生故障之后,會從 ISR 中選出一個新的leader,之后,為保證多個副本之間的數據一致性,其余的 follower 會先將各自的 log 文件高于 HW 的部分截掉,然后從新的 leader同步數據。
注意:這只能保證副本之間的數據一致性,并不能保證數據不丟失或者不重復。
七、關于Kafak高可用性
關于 Kafak高可用性,前面我已經寫了部分,例如:「Kafka的存儲機制、如何保證數據一致性,ISR集合,ACK應答機制等」,這些在面試時被問到都可以談一談,那就面試題,我這里再和大家講講 Kafka的選舉機制。
7.1 Leader 選舉機制
「Kafka的Leader是什么?」
首先Kafka會將接收到的消息分區(partition),每個主題(topic)的消息有不同的分區。這樣一方面消息的存儲就不會受到單一服務器存儲空間大小的限制,另一方面消息的處理也可以在多個服務器上并行。
其次為了保證高可用,每個分區都會有一定數量的副本(replica)。這樣如果有部分服務器不可用,副本所在的服務器就會接替上來,保證應用的持續性。
但是,「為了保證較高的處理效率,消息的讀寫都是在固定的一個副本上完成。這個副本就是所謂的Leader」,而其他副本則是Follower。而Follower則會定期地到Leader上同步數據。
「Leader選舉」
如果某個分區所在的服務器出了問題,不可用,Kafka會從該分區的其他的副本中選擇一個作為新的Leader。之后所有的讀寫就會轉移到這個新的Leader上。現在的問題是應當選擇哪個作為新的Leader。顯然,只有那些跟Leader保持同步的Follower才應該被選作新的Leader。
Kafka會在Zookeeper上針對每個Topic維護一個稱為ISR(in-sync replica,已同步的副本)的集合,該集合中是一些分區的副本。只有當這些副本都跟Leader中的副本同步了之后,Kafka才會認為消息已提交,并反饋給消息的生產者。如果這個集合有增減,Kafka會更新Zookeeper上的記錄。
如果某個分區的Leader不可用,Kafka就會從ISR集合中選擇一個副本作為新的Leader。
顯然通過ISR,Kafka需要的冗余度較低,可以容忍的失敗數比較高。「假設某個topic有f+1個副本,Kafka可以容忍f個服務器不可用。」
「為什么不用少數服從多數的方法?」
少數服從多數是一種比較常見的一致性算法和Leader選舉法。它的含義是只有超過半數的副本同步了,系統才會認為數據已同步;選擇Leader時也是從超過半數的同步的副本中選擇。這種算法需要較高的冗余度。譬如只允許一臺機器失敗,需要有三個副本;而如果只容忍兩臺機器失敗,則需要五個副本。而kafka的ISR集合方法,分別只需要兩個和三個副本。
「如果所有的ISR副本都失敗了怎么辦?」
此時有兩種方法可選,一種是等待ISR集合中的副本復活,一種是選擇任何一個立即可用的副本,而這個副本不一定是在ISR集合中。這兩種方法各有利弊,實際生產中按需選擇。如果要等待ISR副本復活,雖然可以保證一致性,但可能需要很長時間。而如果選擇立即可用的副本,則很可能該副本并不一致。
—?【 THE END 】—本公眾號全部博文已整理成一個目錄,請在公眾號里回復「m」獲取!3T技術資源大放送!包括但不限于:Java、C/C++,Linux,Python,大數據,人工智能等等。在公眾號內回復「1024」,即可免費獲取!!
總結
以上是生活随笔為你收集整理的kafka删除队列_没想到 Kafka 还会这样问,学会这些带你轻松搞定大厂面试!的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 大湾区首个“元宇宙城市&rd
- 下一篇: 苹果用户有福了,群晖按需同步终于支持ma