<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          《面試八股文》之 Kafka 21卷

          共 12093字,需瀏覽 25分鐘

           ·

          2021-09-27 04:43

          大家好,我是 杰哥,作為在消息中間件中擁有神一樣地位的 kafka,你真的了解它嗎?

          其他《面試八股文》系列文章請(qǐng)關(guān)注公號(hào)moon聊技術(shù)獲取~


          • 1.什么是消息中間件?

          • 2.kafka 是什么?有什么作用?

          • 3.kafka 的架構(gòu)是怎么樣的?

          • 4.Kafka Replicas是怎么管理的?

          • 5.如何確定當(dāng)前能讀到哪一條消息?

          • 6.生產(chǎn)者發(fā)送消息有哪些模式?

          • 7.發(fā)送消息的分區(qū)策略有哪些?

          • 8.Kafka 支持讀寫分離嗎?為什么?

          • 9.那 Kafka 是怎么去實(shí)現(xiàn)負(fù)載均衡的?

          • 10.Kafka 的負(fù)責(zé)均衡會(huì)有什么問題呢?

          • 11.Kafka 的可靠性是怎么保證的?

          • 12.Kafka 的消息消費(fèi)方式有哪些?

          • 13.分區(qū)再分配是做什么的?解決了什么問題?

          • 14.副本 leader 是怎么選舉的?

          • 15.分區(qū)數(shù)越多越好嗎?吞吐量就會(huì)越高嗎?

          • 16.如何增強(qiáng)消費(fèi)者的消費(fèi)能力?

          • 17.消費(fèi)者與 topic 的分區(qū)分配策略有哪些?

          • 18.kafka 控制器是什么?有什么作用

          • 19.kafka 控制器是怎么進(jìn)行選舉的?

          • 20.kafka 為什么這么快?

          • 21.什么情況下 kafka 會(huì)丟失消息?

          1.什么是消息中間件?

          消息中間件是基于隊(duì)列與消息傳遞技術(shù),在網(wǎng)絡(luò)環(huán)境中為應(yīng)用系統(tǒng)提供同步或異步、可靠的消息傳輸?shù)闹涡攒浖到y(tǒng)。

          消息中間件利用高效可靠的消息傳遞機(jī)制進(jìn)行平臺(tái)無關(guān)的數(shù)據(jù)交流,并基于數(shù)據(jù)通信來進(jìn)行分布式系統(tǒng)的集成。通過提供消息傳遞和消息排隊(duì)模型,它可以在分布式環(huán)境下擴(kuò)展進(jìn)程間的通信。

          2.kafka 是什么?有什么作用?

          Kafka 是一個(gè)分布式的流式處理平臺(tái),它以高吞吐、可持久化、可水平擴(kuò)展、支持流數(shù)據(jù)處理等多種特性而被廣泛使用

          主要功能體現(xiàn)于三點(diǎn):

          • 消息系統(tǒng):kafka與傳統(tǒng)的消息中間件都具備系統(tǒng)解耦、冗余存儲(chǔ)、流量削峰、緩沖、異步通信、擴(kuò)展性、可恢復(fù)性等功能。與此同時(shí),kafka還提供了大多數(shù)消息系統(tǒng)難以實(shí)現(xiàn)的消息順序性保障及回溯性消費(fèi)的功能。
          • 存儲(chǔ)系統(tǒng):kafka把消息持久化到磁盤,相比于其他基于內(nèi)存存儲(chǔ)的系統(tǒng)而言,有效的降低了消息丟失的風(fēng)險(xiǎn)。這得益于其消息持久化和多副本機(jī)制。也可以將kafka作為長(zhǎng)期的存儲(chǔ)系統(tǒng)來使用,只需要把對(duì)應(yīng)的數(shù)據(jù)保留策略設(shè)置為“永久”或啟用主題日志壓縮功能。
          • 流式處理平臺(tái):kafka為流行的流式處理框架提供了可靠的數(shù)據(jù)來源,還提供了一個(gè)完整的流式處理框架,比如窗口、連接、變換和聚合等各類操作。

          3.kafka 的架構(gòu)是怎么樣的?

          一個(gè)典型的 kafka 體系架構(gòu)包括若干 Producer、若干 Consumer、以及一個(gè) Zookeeper 集群(在2.8.0版本中移,除了 Zookeeper,通過 KRaft 進(jìn)行自己的集群管理)

          Producer 將消息發(fā)送到 Broker,Broker 負(fù)責(zé)將受到的消息存儲(chǔ)到磁盤中,而 Consumer 負(fù)責(zé)從 Broker 訂閱并消費(fèi)消息。

          Kafka 基本概念:

          • Producer :生產(chǎn)者,負(fù)責(zé)將消息發(fā)送到 Broker
          • Consumer :消費(fèi)者,從 Broker 接收消息
          • Consumer Group :消費(fèi)者組,由多個(gè) Consumer 組成。消費(fèi)者組內(nèi)每個(gè)消費(fèi)者負(fù)責(zé)消費(fèi)不同分區(qū)的數(shù)據(jù),一個(gè)分區(qū)只能由一個(gè)組內(nèi)消費(fèi)者消費(fèi);消費(fèi)者組之間互不影響。所有的消費(fèi)者都屬于某個(gè)消費(fèi)者組,即消費(fèi)者組是邏輯上的一個(gè)訂閱者。
          • Broker :可以看做一個(gè)獨(dú)立的 Kafka 服務(wù)節(jié)點(diǎn)或 Kafka 服務(wù)實(shí)例。如果一臺(tái)服務(wù)器上只部署了一個(gè) Kafka 實(shí)例,那么我們也可以將 Broker 看做一臺(tái) Kafka 服務(wù)器。
          • Topic :一個(gè)邏輯上的概念,包含很多 Partition,同一個(gè) Topic 下的 Partiton 的消息內(nèi)容是不相同的
          • Partition :為了實(shí)現(xiàn)擴(kuò)展性,一個(gè)非常大的 topic 可以分布到多個(gè) broker 上,一個(gè) topic 可以分為多個(gè) partition,每個(gè) partition 是一個(gè)有序的隊(duì)列。
          • Replica :副本,同一分區(qū)的不同副本保存的是相同的消息,為保證集群中的某個(gè)節(jié)點(diǎn)發(fā)生故障時(shí),該節(jié)點(diǎn)上的 partition 數(shù)據(jù)不丟失,且 kafka 仍然能夠繼續(xù)工作,kafka 提供了副本機(jī)制,一個(gè) topic 的每個(gè)分區(qū)都有若干個(gè)副本,一個(gè) leader 和若干個(gè) follower。
          • Leader :每個(gè)分區(qū)的多個(gè)副本中的"主副本",生產(chǎn)者以及消費(fèi)者只與 Leader 交互
          • Follower :每個(gè)分區(qū)的多個(gè)副本中的"從副本",負(fù)責(zé)實(shí)時(shí)從 Leader 中同步數(shù)據(jù),保持和 Leader 數(shù)據(jù)的同步。Leader 發(fā)生故障時(shí),從 Follower 副本中重新選舉新的 Leader 副本對(duì)外提供服務(wù)。

          4.Kafka Replicas是怎么管理的?

          • AR:分區(qū)中的所有 Replica 統(tǒng)稱為 AR
          • ISR:所有與 Leader 副本保持一定程度同步的Replica(包括 Leader 副本在內(nèi))組成 ISR
          • OSR:與 Leader 副本同步滯后過多的 Replica 組成了 OSR

          Leader 負(fù)責(zé)維護(hù)和跟蹤 ISR 集合中所有 Follower 副本的滯后狀態(tài),當(dāng) Follower 副本落后過多時(shí),就會(huì)將其放入 OSR 集合,當(dāng) Follower 副本追上了 Leader 的進(jìn)度時(shí),就會(huì)將其放入 ISR 集合。

          默認(rèn)情況下,只有 ISR 中的副本才有資格晉升為 Leader

          5.如何確定當(dāng)前能讀到哪一條消息?

          分區(qū)相當(dāng)于一個(gè)日志文件,我們先簡(jiǎn)單介紹幾個(gè)概念

          如上圖是一個(gè)分區(qū)日志文件

          • 標(biāo)識(shí)共有7條消息,offset (消息偏移量)分別是0~6
          • 0 代表這個(gè)日志文件的開始
          • HW(High Watermark) 為4,0~3 代表這個(gè)日志文件可以消費(fèi)的區(qū)間,消費(fèi)者只能消費(fèi)到這四條消息
          • LEO 代表即將要寫入消息的偏移量 offset

          分區(qū) ISR 集合中的每個(gè)副本都會(huì)維護(hù)自己的 LEO,而 ISR 集合中最小的LEO 即為分區(qū)的 HW

          如上圖: 三個(gè)分區(qū)副本都是 ISR集合當(dāng)中的,最小的 LEO 為 3,就代表分區(qū)的 HW 為3,所以當(dāng)前分區(qū)只能消費(fèi)到 0~2 之間的三條數(shù)據(jù),如下圖

          6.生產(chǎn)者發(fā)送消息有哪些模式?

          總共有三種模式

          • 1.發(fā)后即忘(fire-and-forget)
            • 它只管往 Kafka 里面發(fā)送消息,但是不關(guān)心消息是否正確到達(dá),這種方式的效率最高,但是可靠性也最差,比如當(dāng)發(fā)生某些不可充實(shí)異常的時(shí)候會(huì)造成消息的丟失
          • 2.同步(sync)
            • producer.send()返回一個(gè)Future對(duì)象,調(diào)用get()方法變回進(jìn)行同步等待,就知道消息是否發(fā)送成功,發(fā)送一條消息需要等上個(gè)消息發(fā)送成功后才可以繼續(xù)發(fā)送
          • 3.異步(async)
            • Kafka支持 producer.send() 傳入一個(gè)回調(diào)函數(shù),消息不管成功或者失敗都會(huì)調(diào)用這個(gè)回調(diào)函數(shù),這樣就算是異步發(fā)送,我們也知道消息的發(fā)送情況,然后再回調(diào)函數(shù)中選擇記錄日志還是重試都取決于調(diào)用方

          7.發(fā)送消息的分區(qū)策略有哪些?

          • 1.輪詢:依次將消息發(fā)送該topic下的所有分區(qū),如果在創(chuàng)建消息的時(shí)候 key 為 null,Kafka 默認(rèn)采用這種策略。
          • 2.key 指定分區(qū):在創(chuàng)建消息是 key 不為空,并且使用默認(rèn)分區(qū)器,Kafka 會(huì)將 key 進(jìn)行 hash,然后根據(jù)hash值映射到指定的分區(qū)上。這樣的好處是 key 相同的消息會(huì)在一個(gè)分區(qū)下,Kafka 并不能保證全局有序,但是在每個(gè)分區(qū)下的消息是有序的,按照順序存儲(chǔ),按照順序消費(fèi)。在保證同一個(gè) key 的消息是有序的,這樣基本能滿足消息的順序性的需求。但是如果 partation 數(shù)量發(fā)生變化,那就很難保證 key 與分區(qū)之間的映射關(guān)系了
          • 3.自定義策略:實(shí)現(xiàn) Partitioner 接口就能自定義分區(qū)策略。
          • 4.指定 Partiton 發(fā)送

          8.Kafka 支持讀寫分離嗎?為什么?

          Kafka 是不支持讀寫分離的,那么讀寫分離的好處是什么?主要就是讓一個(gè)節(jié)點(diǎn)去承擔(dān)另一個(gè)節(jié)點(diǎn)的負(fù)載壓力,也就是能做到一定程度的負(fù)載均衡,而且 Kafka 不通過讀寫分離也可以一定程度上去實(shí)現(xiàn)負(fù)載均衡。

          但是對(duì)于 Kafka 的架構(gòu)來說,讀寫分離有兩個(gè)很大的缺點(diǎn)

          • 1.數(shù)據(jù)不一致的問題:讀寫分離必然涉及到數(shù)據(jù)的同步,只要是不同節(jié)點(diǎn)之間的數(shù)據(jù)同步,必然會(huì)有數(shù)據(jù)不一致的問題存在。
          • 2.延時(shí)問題:由于 Kafka 獨(dú)特的數(shù)據(jù)處理方式,導(dǎo)致如果將數(shù)據(jù)從一個(gè)節(jié)點(diǎn)同步到另一個(gè)節(jié)點(diǎn)必然會(huì)經(jīng)過主節(jié)點(diǎn)磁盤和從節(jié)點(diǎn)磁盤,對(duì)一些延時(shí)性要求較高的應(yīng)用來說,并不太適用

          9.那 Kafka 是怎么去實(shí)現(xiàn)負(fù)載均衡的?

          Kafka 的負(fù)責(zé)均衡主要是通過分區(qū)來實(shí)現(xiàn)的,我們知道 Kafka 是主寫主讀的架構(gòu),如下圖:

          共三個(gè) broker ,里面各有三個(gè)副本,總共有三個(gè) partation, 深色的是 leader,淺色的是 follower,上下灰色分別代表生產(chǎn)者和消費(fèi)者,虛線代表 follower 從 leader 拉取消息。

          我們從這張圖就可以很明顯的看出來,每個(gè) broker 都有消費(fèi)者拉取消息,每個(gè) broker 也都有生產(chǎn)者發(fā)送消息,每個(gè) broker 上的讀寫負(fù)載都是一樣的,這也說明了 kafka 獨(dú)特的架構(gòu)方式可以通過主寫主讀來實(shí)現(xiàn)負(fù)載均衡。

          10.Kafka 的負(fù)責(zé)均衡會(huì)有什么問題呢?

          kafka的負(fù)載均衡在絕對(duì)理想的狀況下可以實(shí)現(xiàn),但是會(huì)有某些情況出現(xiàn)一定程度上的負(fù)載不均衡

          • 1.broker 端分配不均:當(dāng)創(chuàng)建 topic 的時(shí)候可能會(huì)出現(xiàn)某些 broker 分配到的分區(qū)數(shù)多,而有些 broker 分配的分區(qū)少,這就導(dǎo)致了 leader 多副本不均。
          • 2.生產(chǎn)者寫入消息不均:生產(chǎn)者可能只對(duì)某些 broker 中的 leader 副本進(jìn)行大量的寫入操作,而對(duì)其他的 leader 副本不聞不問。
          • 3.消費(fèi)者消費(fèi)不均:消費(fèi)者可能只對(duì)某些 broker 中的 leader 副本進(jìn)行大量的拉取操作,而對(duì)其他的 leader 副本不聞不問。
          • 4.leader 副本切換不均:當(dāng)主從副本切換或者分區(qū)副本進(jìn)行了重分配后,可能會(huì)導(dǎo)致各個(gè) broker 中的 leader 副本分配不均勻。

          11.Kafka 的可靠性是怎么保證的?

          1.acks

          這個(gè)參數(shù)用來指定分區(qū)中有多少個(gè)副本收到這條消息,生產(chǎn)者才認(rèn)為這條消息是寫入成功的,這個(gè)參數(shù)有三個(gè)值:

          • 1.acks = 1,默認(rèn)為1。生產(chǎn)者發(fā)送消息,只要 leader 副本成功寫入消息,就代表成功。這種方案的問題在于,當(dāng)返回成功后,如果 leader 副本和 follower 副本還沒有來得及同步,leader 就崩潰了,那么在選舉后新的 leader 就沒有這條消息,也就丟失了
          • 2.acks = 0。生產(chǎn)者發(fā)送消息后直接算寫入成功,不需要等待響應(yīng)。這個(gè)方案的問題很明顯,只要服務(wù)端寫消息時(shí)出現(xiàn)任何問題,都會(huì)導(dǎo)致消息丟失
          • 3.acks = -1 或 acks = all。生產(chǎn)者發(fā)送消息后,需要等待 ISR 中的所有副本都成功寫入消息后才能收到服務(wù)端的響應(yīng)。毫無疑問這種方案的可靠性是最高的,但是如果 ISR 中只有l(wèi)eader 副本,那么就和 acks = 1 毫無差別了。

          2.消息發(fā)送的方式

          第6問中我們提到了生產(chǎn)者發(fā)送消息有三種方式,發(fā)完即忘,同步和異步。我們可以通過同步或者異步獲取響應(yīng)結(jié)果,失敗做重試來保證消息的可靠性。

          3.手動(dòng)提交位移

          默認(rèn)情況下,當(dāng)消費(fèi)者消費(fèi)到消息后,就會(huì)自動(dòng)提交位移。但是如果消費(fèi)者消費(fèi)出錯(cuò),沒有進(jìn)入真正的業(yè)務(wù)處理,那么就可能會(huì)導(dǎo)致這條消息消費(fèi)失敗,從而丟失。我們可以開啟手動(dòng)提交位移,等待業(yè)務(wù)正常處理完成后,再提交offset。

          4.通過副本 LEO 來確定分區(qū) HW

          可參考第五問

          12.Kafka 的消息消費(fèi)方式有哪些?

          一般消息消費(fèi)有兩種模式,推和拉。Kafka的消費(fèi)是屬于拉模式的,而此模式的消息消費(fèi)方式有兩種,點(diǎn)對(duì)點(diǎn)和發(fā)布訂閱

          • 1.點(diǎn)對(duì)點(diǎn):如果所有消費(fèi)者屬于同一個(gè)消費(fèi)組,那么所有的消息都會(huì)被均勻的投遞給每一個(gè)消費(fèi)者,每條消息只會(huì)被其中一個(gè)消費(fèi)者消費(fèi)
          • 2.發(fā)布訂閱:如果所有消費(fèi)者屬于不同的消費(fèi)組,那么所有的消息都會(huì)被投遞給每一個(gè)消費(fèi)者,每個(gè)消費(fèi)者都會(huì)收到該消息

          13.分區(qū)再分配是做什么的?解決了什么問題?

          分區(qū)再分配主要是用來維護(hù) kafka 集群的負(fù)載均衡

          既然是分區(qū)再分配,那么 kafka 分區(qū)有什么問題呢?

          • 問題1:當(dāng)集群中的一個(gè)節(jié)點(diǎn)下線了
            • 如果該節(jié)點(diǎn)的分區(qū)是單副本的,那么分區(qū)將會(huì)變得不可用
            • 如果是多副本的,就會(huì)進(jìn)行 leader 選舉,在其他機(jī)器上選舉出新的 leader

          kafka 并不會(huì)將這些失效的分區(qū)遷移到其他可用的 broker 上,這樣就會(huì)影響集群的負(fù)載均衡,甚至也會(huì)影響服務(wù)的可靠性和可用性

          • 問題2:當(dāng)集群新增 broker 時(shí),只有新的主題分區(qū)會(huì)分配在該 broker 上,而老的主題分區(qū)不會(huì)分配在該 broker 上,就造成了老節(jié)點(diǎn)和新節(jié)點(diǎn)之間的負(fù)載不均衡

          為了解決該問題就出現(xiàn)了分區(qū)再分配,它可以在集群擴(kuò)容,broker 失效的場(chǎng)景下進(jìn)行分區(qū)遷移。

          分區(qū)再分配的原理就是通化控制器給分區(qū)新增新的副本,然后通過網(wǎng)絡(luò)把舊的副本數(shù)據(jù)復(fù)制到新的副本上,在復(fù)制完成后,將舊副本清除。 當(dāng)然,為了不影響集群正常的性能,在此復(fù)制期間還會(huì)有一些列保證性能的操作,比如復(fù)制限流

          14.副本 leader 是怎么選舉的?

          當(dāng)分區(qū) leader 節(jié)點(diǎn)崩潰時(shí),其中一個(gè) follower 節(jié)點(diǎn)會(huì)成為新的 leader 節(jié)點(diǎn),這樣會(huì)導(dǎo)致集群的負(fù)載不均衡,從而影響服務(wù)的健壯性和穩(wěn)定性

          如下:

          Topic: test Partation:0 Leader:1 Replicas:1,2,0 Isr:1,2,0
          Topic: test Partation:1 Leader:2 Replicas:2,0,1 Isr:2,0,1
          Topic: test Partation:2 Leader:0 Replicas:0,1,2 Isr:0,1,2

          我們可以看到

          • 0 分區(qū) 1 是 leader
          • 1 分區(qū) 2 是 leader
          • 2 分區(qū) 0 是 leader

          如果此時(shí)中間的節(jié)點(diǎn)重啟

          Topic: test Partation:0 Leader:1 Replicas:1,2,0 Isr:1,0,2
          Topic: test Partation:1 Leader:0 Replicas:2,0,1 Isr:0,1,2
          Topic: test Partation:2 Leader:0 Replicas:0,1,2 Isr:0,1,2

          我們又可以看到:

          • 0 分區(qū) 1 是 leader
          • 1 分區(qū) 0 是 leader
          • 2 分區(qū) 0 是 leader

          我們會(huì)發(fā)現(xiàn),原本 1 分區(qū)有兩個(gè) ledaer,經(jīng)過重啟后 leader 都消失了,如此就負(fù)載不均衡了。

          為了解決這種問題,就引入了優(yōu)先副本的概念

          優(yōu)先副本就是說在 AR 集合中的第一個(gè)副本。比如分區(qū) 2 的 AR 為 0,1,2,那么分區(qū) 2 的優(yōu)先副本就為0。理想情況下優(yōu)先副本就是 leader 副本。優(yōu)先副本選舉就是促使優(yōu)先副本成為 leader 副本,從而維護(hù)集群的負(fù)載均衡。

          15.分區(qū)數(shù)越多越好嗎?吞吐量就會(huì)越高嗎?

          一般類似于這種問題的答案,都是持否定態(tài)度的。

          但是可以說,在一定條件下,分區(qū)數(shù)的數(shù)量是和吞吐量成正比的,分區(qū)數(shù)和性能也是成正比的

          那么為什么說超過了一定限度,就會(huì)對(duì)性能造成影響呢?原因如下:

          1.客戶端/服務(wù)器端需要使用的內(nèi)存就越多

          • 服務(wù)端在很多組件中都維護(hù)了分區(qū)級(jí)別的緩存,分區(qū)數(shù)越大,緩存成本也就越大。
          • 消費(fèi)端的消費(fèi)線程數(shù)是和分區(qū)數(shù)掛鉤的,分區(qū)數(shù)越大消費(fèi)線程數(shù)也就越多,線程的開銷成本也就越大
          • 生產(chǎn)者發(fā)送消息有緩存的概念,會(huì)為每個(gè)分區(qū)緩存消息,當(dāng)積累到一定程度或者時(shí)間時(shí)會(huì)將消息發(fā)送到分區(qū),分區(qū)越多,這部分的緩存也就越大

          2.文件句柄的開銷

          每個(gè) partition 都會(huì)對(duì)應(yīng)磁盤文件系統(tǒng)的一個(gè)目錄。在 Kafka 的數(shù)據(jù)日志文件目錄中,每個(gè)日志數(shù)據(jù)段都會(huì)分配兩個(gè)文件,一個(gè)索引文件和一個(gè)數(shù)據(jù)文件。每個(gè) broker 會(huì)為每個(gè)日志段文件打開一個(gè) index 文件句柄和一個(gè)數(shù)據(jù)文件句柄。因此,隨著 partition 的增多,所需要保持打開狀態(tài)的文件句柄數(shù)也就越多,最終可能超過底層操作系統(tǒng)配置的文件句柄數(shù)量限制。

          3.越多的分區(qū)可能增加端對(duì)端的延遲

          Kafka 會(huì)將分區(qū) HW 之前的消息暴露給消費(fèi)者。分區(qū)越多則副本之間的同步數(shù)量就越多,在默認(rèn)情況下,每個(gè) broker 從其他 broker 節(jié)點(diǎn)進(jìn)行數(shù)據(jù)副本復(fù)制時(shí),該 broker 節(jié)點(diǎn)只會(huì)為此工作分配一個(gè)線程,該線程需要完成該 broker 所有 partition 數(shù)據(jù)的復(fù)制。

          4.降低高可用性

          在第 13 問我們提到了分區(qū)再分配,會(huì)將數(shù)據(jù)復(fù)制到另一份副本當(dāng)中,分區(qū)數(shù)量越多,那么恢復(fù)時(shí)間也就越長(zhǎng),而如果發(fā)生宕機(jī)的 broker 恰好是 controller 節(jié)點(diǎn)時(shí):在這種情況下,新 leader 節(jié)點(diǎn)的選舉過程在 controller 節(jié)點(diǎn)恢復(fù)到新的 broker 之前不會(huì)啟動(dòng)。controller 節(jié)點(diǎn)的錯(cuò)誤恢復(fù)將會(huì)自動(dòng)地進(jìn)行,但是新的 controller 節(jié)點(diǎn)需要從 zookeeper 中讀取每一個(gè) partition 的元數(shù)據(jù)信息用于初始化數(shù)據(jù)。例如,假設(shè)一個(gè)Kafka 集群存在 10000個(gè)partition,從 zookeeper 中恢復(fù)元數(shù)據(jù)時(shí)每個(gè) partition 大約花費(fèi) 2 ms,則 controller 的恢復(fù)將會(huì)增加約 20 秒的不可用時(shí)間窗口。

          16.如何增強(qiáng)消費(fèi)者的消費(fèi)能力?

          • 1.可以考慮增加 topic 的分區(qū)數(shù),并且同時(shí)提升消費(fèi)組的消費(fèi)者數(shù)量,消費(fèi)者數(shù)=分區(qū)數(shù)。
          • 2.如果是消費(fèi)者消費(fèi)不及時(shí),可以采用多線程的方式進(jìn)行消費(fèi),并且優(yōu)化業(yè)務(wù)方法流程,同樣的分區(qū)數(shù),為什么人家并發(fā)那么高,你的就不行??


          17.消費(fèi)者與 topic 的分區(qū)分配策略有哪些?

          1.RangeAssignor 分配策略

          該分配策略是按照消費(fèi)者總數(shù)和分區(qū)總數(shù)進(jìn)行整除運(yùn)算來獲得一個(gè)跨度,然后分區(qū)按照跨度來進(jìn)行平均分配,盡可能保證分區(qū)均勻的分配給所有的消費(fèi)者。

          對(duì)于每個(gè) topic,該策略會(huì)講消費(fèi)者組內(nèi)所有訂閱這個(gè)主題的消費(fèi)者按照名稱的字典順序排序,然后為每個(gè)消費(fèi)者劃分固定過的區(qū)域,如果不夠平均分配,那么字典排序考前的就會(huì)多分配一個(gè)分區(qū)

          比如 2 個(gè)消費(fèi)者屬于一個(gè)消費(fèi)者組,有 2 個(gè) topic t1,t2,每個(gè) topic 都有 3 個(gè)分區(qū),p1,p2,p3,那么分配的情況如下:

            消費(fèi)者A:t0-p0,t0-p1,t1-p0,t1-p1,
            消費(fèi)者B:t0-p2,t1-p2

          這樣就會(huì)出現(xiàn)非配不均勻的情況

          2.RoundRobinAssignor 分配策略

          該分配策略是按將消費(fèi)者組內(nèi)所有消費(fèi)者及消費(fèi)者訂閱的所有主題的分區(qū)按照字典排序,然后通過輪詢的方式分配給每個(gè)消費(fèi)者

          比如有 3 個(gè)消費(fèi)者 A,B,C,訂閱了 3 個(gè) topic ,t0,t1,t2,每個(gè) topic 各有 3 個(gè)分區(qū) p0,p1,p2。如果 A 訂閱了 t0,B 訂閱了 t0 和 t1,C 訂閱了 t0,t1,t2,那么分配的情況如下:

            消費(fèi)者A:t0-p0
            消費(fèi)者B:t1-p0
            消費(fèi)者C:t1-p1,t2-p0,t2-p1,t2-p2

          這樣也會(huì)出現(xiàn)分配不均勻的情況,按照訂閱情況來講完全可以吧 t1p1 分配給消費(fèi)者B

          3.StickyAssignor分配策略

          這種分配策略有兩個(gè)目的

          • 1.分區(qū)的分配要盡可能的均勻
          • 2.分區(qū)的分配盡可能的與上次分配的保持相同。

          當(dāng)兩者發(fā)生沖突時(shí),第一個(gè)目標(biāo)優(yōu)先于第二個(gè)目標(biāo)。

          假設(shè)消費(fèi)組內(nèi)有3個(gè)消費(fèi)者:C0、C1、C2
          它們都訂閱了4個(gè)主題:t0、t1、t2、t3
          并且每個(gè)主題有2個(gè)分區(qū),也就是說整個(gè)消費(fèi)組訂閱了,t0p0、t0p1、t1p0、t1p1、t2p0、t2p1、t3p0、t3p1 這8個(gè)分區(qū)
          最終的分配結(jié)果如下:

          消費(fèi)者C0:t0p0、t1p1、t3p0

          消費(fèi)者C1:t0p1、t2p0、t3p1

          消費(fèi)者C2:t1p0、t2p1

          這樣初看上去似乎與采用RoundRobinAssignor策略所分配的結(jié)果相同

          此時(shí)假設(shè)消費(fèi)者C1脫離了消費(fèi)組,那么消費(fèi)組就會(huì)執(zhí)行再平衡操作,進(jìn)而消費(fèi)分區(qū)會(huì)重新分配。如果采用RoundRobinAssignor策略,那么此時(shí)的分配結(jié)果如下:

          消費(fèi)者C0:t0p0、t1p0、t2p0、t3p0

          消費(fèi)者C2:t0p1、t1p1、t2p1、t3p1

          如分配結(jié)果所示,RoundRobinAssignor策略會(huì)按照消費(fèi)者C0和C2進(jìn)行重新輪詢分配。而如果此時(shí)使用的是StickyAssignor策略,那么分配結(jié)果為:

          消費(fèi)者C0:t0p0、t1p1、t3p0、t2p0

          消費(fèi)者C2:t1p0、t2p1、t0p1、t3p1

          可以看到分配結(jié)果中保留了上一次分配中對(duì)于消費(fèi)者C0和C2的所有分配結(jié)果,并將原來消費(fèi)者C1的“負(fù)擔(dān)”分配給了剩余的兩個(gè)消費(fèi)者C0和C2,最終C0和C2的分配還保持了均衡。

          如果發(fā)生分區(qū)重分配,那么對(duì)于同一個(gè)分區(qū)而言有可能之前的消費(fèi)者和新指派的消費(fèi)者不是同一個(gè),對(duì)于之前消費(fèi)者進(jìn)行到一半的處理還要在新指派的消費(fèi)者中再次復(fù)現(xiàn)一遍,這顯然很浪費(fèi)系統(tǒng)資源。StickyAssignor策略如同其名稱中的“sticky”一樣,讓分配策略具備一定的“粘性”,盡可能地讓前后兩次分配相同,進(jìn)而減少系統(tǒng)資源的損耗以及其它異常情況的發(fā)生

          到目前為止所分析的都是消費(fèi)者的訂閱信息都是相同的情況,我們來看一下訂閱信息不同的情況下的處理。

          舉例:同樣消費(fèi)組內(nèi)有3個(gè)消費(fèi)者:C0、C1、C2
          集群中有3個(gè)主題 t0、t1、t2
          這3個(gè)主題分別有 1、2、3個(gè)分區(qū)
          也就是說集群中有 t0p0、t1p0、t1p1、t2p0、t2p1、t2p2 這6個(gè)分區(qū)
          消費(fèi)者C0訂閱了主題t0,消費(fèi)者C1訂閱了主題t0和t1,消費(fèi)者C2訂閱了主題t0、t1和t2
          如果此時(shí)采用RoundRobinAssignor策略:

          消費(fèi)者C0:t0p0

          消費(fèi)者C1:t1p0

          消費(fèi)者C2:t1p1、t2p0、t2p1、t2p2

          如果此時(shí)采用的是StickyAssignor策略:

          消費(fèi)者C0:t0p0

          消費(fèi)者C1:t1p0、t1p1

          消費(fèi)者C2:t2p0、t2p1、t2p2

          此時(shí)消費(fèi)者C0脫離了消費(fèi)組,那么RoundRobinAssignor策略的分配結(jié)果為:

          消費(fèi)者C1:t0p0、t1p1

          消費(fèi)者C2:t1p0、t2p0、t2p1、t2p2

          StickyAssignor策略,那么分配結(jié)果為:

          消費(fèi)者C1:t1p0、t1p1、t0p0

          消費(fèi)者C2:t2p0、t2p1、t2p2

          可以看到StickyAssignor策略保留了消費(fèi)者C1和C2中原有的5個(gè)分區(qū)的分配:

          t1p0、t1p1、t2p0、t2p1、t2p2。

          從結(jié)果上看StickyAssignor策略比另外兩者分配策略而言顯得更加的優(yōu)異,這個(gè)策略的代碼實(shí)現(xiàn)也是異常復(fù)雜。

          4.自定義分區(qū)分配策略

          可以通過實(shí)現(xiàn) org.apache.kafka.clients.consumer.internals.PartitionAssignor 接口來實(shí)現(xiàn)

          18.kafka 控制器是什么?有什么作用

          在 Kafka 集群中會(huì)有一個(gè)或多個(gè) broker,其中有一個(gè) broker 會(huì)被選舉為控制器,它負(fù)責(zé)管理整個(gè)集群中所有分區(qū)和副本的狀態(tài),kafka 集群中只能有一個(gè)控制器

          • 當(dāng)某個(gè)分區(qū)的 leader 副本出現(xiàn)故障時(shí),由控制器負(fù)責(zé)為該分區(qū)選舉新的 leader 副本
          • 當(dāng)檢測(cè)到某個(gè)分區(qū)的ISR集合發(fā)生變化時(shí),由控制器負(fù)責(zé)通知所有 broker 更新其元數(shù)據(jù)信息
          • 當(dāng)為某個(gè) topic 增加分區(qū)數(shù)量時(shí),由控制器負(fù)責(zé)分區(qū)的重新分配

          19.kafka 控制器是怎么進(jìn)行選舉的?

          kafka 中的控制器選舉工作依賴于 Zookeeper,成功競(jìng)選成為控制器的 broker 會(huì)在Zookeeper中創(chuàng)建/controller臨時(shí)節(jié)點(diǎn)。

          每個(gè) broker 啟動(dòng)的時(shí)候會(huì)去嘗試讀取/controller 節(jié)點(diǎn)的 brokerid的值

          • 如果讀取到的 brokerid 的值不為-1,表示已經(jīng)有其他broker 節(jié)點(diǎn)成功競(jìng)選為控制器,所以當(dāng)前 broker 就會(huì)放棄競(jìng)選

          如果Zookeeper中不存在/controller 節(jié)點(diǎn),或者這個(gè)節(jié)點(diǎn)的數(shù)據(jù)異常,那么就會(huì)嘗試去創(chuàng)建/controller 節(jié)點(diǎn),創(chuàng)建成功的那個(gè) broker 就會(huì)成為控制器

          每個(gè) broker 都會(huì)在內(nèi)存中保存當(dāng)前控制器的 brokerid 值,這個(gè)值可以標(biāo)識(shí)為 activeControllerId。

          Zookeeper 中還有一個(gè)與控制器有關(guān)的/controller_epoch 節(jié)點(diǎn),這個(gè)節(jié)點(diǎn)是持久節(jié)點(diǎn),節(jié)點(diǎn)中存放的是一個(gè)整型的 controller_epoch 值。controller_epoch 值用于記錄控制器發(fā)生變更的次數(shù)

          controller_epoch 的初始值為1,即集群中的第一個(gè)控制器的紀(jì)元為1,當(dāng)控制器發(fā)生變更時(shí),每選出一個(gè)新的控制器就將該字段值加1

          每個(gè)和控制器交互的請(qǐng)求都會(huì)攜帶 controller_epoch 這個(gè)字段,

          • 如果請(qǐng)求的 controller_epoch 值小于內(nèi)存中的 controller_epoch值認(rèn)為這個(gè)請(qǐng)求是向已經(jīng)過期的控制器發(fā)送的請(qǐng)求,那么這個(gè)請(qǐng)求會(huì)被認(rèn)定為無效的請(qǐng)求
          • 如果請(qǐng)求的 controller_epoch 值大于內(nèi)存中的 controller_epoch值,那么說明已經(jīng)有新的控制器當(dāng)選

          20.kafka 為什么這么快?

          • 1.順序讀寫

            磁盤分為順序讀寫與隨機(jī)讀寫,基于磁盤的隨機(jī)讀寫確實(shí)很慢,但磁盤的順序讀寫性能卻很高,kafka 這里采用的就是順序讀寫。

          • 2.Page Cache

            為了優(yōu)化讀寫性能,Kafka 利用了操作系統(tǒng)本身的 Page Cache,就是利用操作系統(tǒng)自身的內(nèi)存而不是JVM空間內(nèi)存。

          • 3.零拷貝

            Kafka使用了零拷貝技術(shù),也就是直接將數(shù)據(jù)從內(nèi)核空間的讀緩沖區(qū)直接拷貝到內(nèi)核空間的 socket 緩沖區(qū),然后再寫入到 NIC 緩沖區(qū),避免了在內(nèi)核空間和用戶空間之間穿梭。

          • 4.分區(qū)分段+索引

            Kafka 的 message 是按 topic分 類存儲(chǔ)的,topic 中的數(shù)據(jù)又是按照一個(gè)一個(gè)的 partition 即分區(qū)存儲(chǔ)到不同 broker 節(jié)點(diǎn)。每個(gè) partition 對(duì)應(yīng)了操作系統(tǒng)上的一個(gè)文件夾,partition 實(shí)際上又是按照segment分段存儲(chǔ)的。

            通過這種分區(qū)分段的設(shè)計(jì),Kafka 的 message 消息實(shí)際上是分布式存儲(chǔ)在一個(gè)一個(gè)小的 segment 中的,每次文件操作也是直接操作的 segment。為了進(jìn)一步的查詢優(yōu)化,Kafka 又默認(rèn)為分段后的數(shù)據(jù)文件建立了索引文件,就是文件系統(tǒng)上的.index文件。這種分區(qū)分段+索引的設(shè)計(jì),不僅提升了數(shù)據(jù)讀取的效率,同時(shí)也提高了數(shù)據(jù)操作的并行度。

          • 5.批量讀寫

            Kafka 數(shù)據(jù)讀寫也是批量的而不是單條的,這樣可以避免在網(wǎng)絡(luò)上頻繁傳輸單個(gè)消息帶來的延遲和帶寬開銷。假設(shè)網(wǎng)絡(luò)帶寬為10MB/S,一次性傳輸10MB的消息比傳輸1KB的消息10000萬次顯然要快得多。

          • 6.批量壓縮

            Kafka 把所有的消息都變成一個(gè)批量的文件,并且進(jìn)行合理的批量壓縮,減少網(wǎng)絡(luò) IO 損耗,通過 mmap 提高 I/O 速度,寫入數(shù)據(jù)的時(shí)候由于單個(gè)Partion是末尾添加所以速度最優(yōu);讀取數(shù)據(jù)的時(shí)候配合 sendfile 進(jìn)行直接讀取。

          21.什么情況下 kafka 會(huì)丟失消息?

          Kafka 有三次消息傳遞的過程:生產(chǎn)者發(fā)消息給 Broker,Broker 同步消息和持久化消息,Broker 將消息傳遞給消費(fèi)者。

          這其中每一步都有可能丟失消息.

          • 1.生產(chǎn)者發(fā)送數(shù)據(jù): 在第 11 問中的 acks中有說到

            • 當(dāng) acks 為 0,只要服務(wù)端寫消息時(shí)出現(xiàn)任何問題,都會(huì)導(dǎo)致消息丟失
            • 當(dāng) acks 配置為 1 時(shí),生產(chǎn)者發(fā)送消息,只要 leader 副本成功寫入消息,就代表成功。這種方案的問題在于,當(dāng)返回成功后,如果 leader 副本和 follower 副本還沒有來得及同步,leader 就崩潰了,那么在選舉后新的 leader 就沒有這條消息,也就丟失了
          • 2.Broker 存儲(chǔ)數(shù)據(jù):kafka 通過 Page Cache 將數(shù)據(jù)寫入磁盤。

            • Page Cache 就是當(dāng)往磁盤文件寫入的時(shí)候,系統(tǒng)會(huì)先將數(shù)據(jù)流寫入緩存中,但是什么時(shí)候?qū)⒕彺娴臄?shù)據(jù)寫入文件中是由操作系統(tǒng)自行決定。所以如果此時(shí)機(jī)器突然掛了,也是會(huì)丟失消息的
          • 3.消費(fèi)者消費(fèi)數(shù)據(jù):在開啟自動(dòng)提交 offset 時(shí),只要消費(fèi)者消費(fèi)到消息,那么就會(huì)自動(dòng)提交偏移量,如果業(yè)務(wù)還沒有來得及處理,那么消息就會(huì)丟失

          推薦閱讀

          圖解 Kafka!


          入門 Kafka


          瀏覽 65
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  ww国产| 国产69久久成人看精品 | 日本韩国一区二区三区在线观看 | 亚洲精品国产精品自产 | 成人日日夜夜精品 |