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