Kafaka核心概念與原理


一、什么是消費者組、分區

在Kafka中,同一主題下,支持“消費者組”的概念,即一個消息可以被不同的消費者消費,一個消息只能被同組內一個消費者消費

 

        

 

 

 

 分區:partition,一個Topic有多個分區,分區內的消息是有序的。(一個分區只屬於單個主題,同一主題下的不同分區包含的消息不同)

  一個分區只能同時被同消費者組的一個消費者消費

在分區中還有一個概念:offset,offset是消息在分區中的唯一標識,消息被追加到分區日志文件的時候都會分配一個特定的偏移量

 

 

(問)Kafka如何保證消息的全局有序?

 全局使用一個生產者,全局使用一個消費者,全局使用一個分區

 

 

從使用層面來看,Kafka的高性能體現在:

   1、多分區並行消費

  2、數據壓縮+消息批量發送,節省網絡IO開銷

 

 

partition的數量無上限,但並不意味着越多越好

 1、越多的分區可以提供更高的吞吐量

 2、越多的分區需要打開更多的文件句柄

 3、越多的分區會導致消費者消費的延遲越高

 4、越多的分區意味着需要更多的內存

 5、越多的partition會導致更長時間的恢復期

 

二、Kafka的分區策略

分區策略:即“該消息要發送給哪個分區”

 1.指定分區號【場景很少】

 2.根據分區Key值Hash

   

 

 3.輪詢發送【消息無需有序的場景,如審計信息】

 

 

 4.自定義分區策略(實現PartitionAssignor接口)

 

 

 

三、Kafka的Producer配置

SpringBoot集成Kafka生產者配置文件實例

 

Producer配置之request.required.asks

  0:相當於異步的,不需要leader給予回復,producer立即返回,發送就是成功。那么發送消息網絡超時或broker崩潰,既有可能丟失也可能會重發。

  1:當leader接收到消息之后發送ack,失敗會重試,丟的概率很小。

  -1:當大部分的ISR的follower都同步消息成功后發送ack,丟失消息可能性比較低。(與后面配置的ISR數量有關)

 

 

四、Kafka的Consumer

消息消費方式:

 1、PUSH:消息隊列主動地將消息推送給消費者

 2、PULL(Kafka消費方式):由消費者客戶端主動向消息隊列拉去消息

 

PUSH方式:消息實時性高,但沒有考慮客戶端的消費能力

PULL方式:消息實時性低,可能造成大量無效請求

 

 

消費者Kafka基礎配置【以SpringBoot集成Kafka為例】

 

消費者Kafka其他配置【以SpringBoot集成Kafka為例】

enable-auto-commit:是否開啟自動提交

auto-offset-reset:從哪里開始消費

 

 

五、分區分配策略

分區分配策略:即“此分區內的消息應該由誰來消費”?【同一個分區只能被同組的一個消費者消費】

 

一、RangeAssignor[默認]: Range

說明:對同一個 topic 里面的分區按照序號進行排序,並對消費者按照字母順序進行排序。通過 partitions數/consumer數 來決定每個消費者應該消費幾個分區。如果除不盡,那么前面幾個消費者將會多  消費 1 個分區。

弊端:多topic時,負載不均衡。前面的Consumer分配的分區過多

 

 

 

 

二、RoundRobinAssignor:Round Robin【大多數場景此策略可以滿足】

說明:把所有的 partition 和所有的 consumer 都列出來,然后按照 hashcode 進行排序,最后通過輪詢算法來分配 partition 給到各個消費者。

弊端:當不是適合的場景情況下,分配不完美,當且僅當如下情況時才均勻:

    ① 每個消費者訂閱的主題,必須是相同的 

    ② 每個主題的消費者實例都是相同的   

 

 

三、StickyAssignor:粘性策略

說明:分區的分配要盡可能的均勻;分區的分配盡可能的與上次分配的保持相同。 當兩者發生沖突時,第一個目標優先於第二個目標。

 

 

 

 

Kafka Rebalance機制:即“分區重新分配”

觸發時機:【變量:Topic數、分區數、消費者數】

1、組成員個數發生變化(有新的 consumer 實例加入該消費組或者離開組)

  服務滾動部署(來回啟動、關閉)

  服務宕機重啟

  Consumer性能不足,誤判離線

2、訂閱 Topic 的分區數發生變化。

  分區擴容

3、訂閱的 Topic 個數發生變化。

 

 

Kafka Rebalance過程(以Eager Rebalance Protocol為例):

 

簡單描述:(當上述觸發時機發生時觸發此過程)

1、GroupCoordinator得知需要觸發Rebalance,拒絕所有消費者的心跳同時返回[Rebalance]事件。

2、消費者不再心跳,而是向GroupCoordinator發送JoinGroupRequest請求。

3、GroupCoordinator(組協調器) 從 Consumer Group 選出 Leader。

4、由Leader根據分區分配策略,計算消費關系,將結果返回給GroupCoordinator。

5、GroupCoordinator將結果通知到各個Consumer。

重點:Rebalance過程中,所有消費者停止消費,應當盡量避免Rebalance的發生

 

如何判斷Consumer存活還是假死?

假死判斷:消費者有心跳,但是不干活

存活判斷:心跳(定時發請求)

 

Broker與Consumer存活的雙向檢測:

 

心跳檢測相關參數:

Broker端參數:

  group.min.session.timeout.ms:已注冊的消費者允許的會話超時的最小時長,小於便拒絕此心跳請求。(防止頻繁接收心跳請求,影響效率)

  group.max.session.timeout.ms:已注冊的消費者允許的會話超時的最大時長,大於則認為是消費者離線。

Consumer端參數:

  session.timout.ms: Consumer session 過期時間,距離上次心跳成功的時間,超過此時間,會認為Broker不可用。【判斷Broker不可用】

    Consumer的session.timout.ms介於Broker的min與max之間

  heartbeat.interval.ms:心跳間隔。

    通常設置的值要低於session.timeout.ms的1/3  (可能消費者突然性能下降,無法及時消費,但是並沒有下線,設置1/3,就有兩次重新發送心跳請求的時間)

 

數據拉取線程相關參數:

  max.poll.interval.ms:長時間沒有調用pull,且間隔超過這個值時,consumer判定自身為假死,自動離線。【判斷自身不可用】

思考:從max.poll.interval.ms參數來看,如何減少Rebalance的發生?      一次業務處理時長不得超過 max.poll.interval.ms

 

 

 

六、Kafka消息存儲機制

 

Kafka 消息是采用 Segment 的存儲方式進行存儲的,每個分區文件夾下拆分為N個小文件,共同存儲修改分區中的所有消息。

一個日志段,有3個文件:

  數據文件(Data File):存數據,新消息追加寫在后面

  數據文件分段:segment

  索引文件(Index File):采用稀疏索引,每隔一定字節的數據建立一條索引,這樣的話就是避免了索引文件占用過多的空間和資源,從而可以將索引文件保留到內存中。缺點是沒有建立索引的數據在查詢的過程中需要小范圍內的順序掃描操作。

 

索引文件如何使用?比如:要查找絕對offset為7的Message:

1、用二分查找確定它是在哪個LogSegment中,自然是在第一個Segment中。

2、打開這個Segment的index文件,也是用二分查找找到offset小於或者等於指定offset的索引條目中最大的那個offset。自然offset為6的那個索引是我們要找的,通過索引文件我們知道offset為6的Message在數據文件中的位置為9807。

3、打開數據文件,從位置為9807的那個地方開始順序掃描直到找到offset為7的那條Message。

 

Kafka的高性能還體現在它的存儲機制上,因為Kafka消息的存儲采用了稀疏索引,寫數據不需要每次都寫索引文件,提高性能

分段存儲的好處? 

   1、讀取效率高 

   2、方便消息清理,僅刪除,無修改

 

Kafka 中每個分區是一個有序的,不可變的消息序列,新的消息不斷追加到 partition 的末尾,這個就是順序寫。

 

磁盤完成一個I/O請求所花費的時間 = 尋道時間 + 旋轉延遲 + 數據傳輸時間

連續 I/O與隨機I/O

  連續I/O:指的是本次 I/O 給出的初始扇區地址和上一次 I/O 的結束扇區地址是完全連續或者相隔不多的。

  隨機I/O:反之,如果相差很大,則算作一次隨機 I/O。

連續 I/O 比隨機 I/O 效率高的原因是:在做連續 I/O 的時候,磁頭幾乎不用換道,或者換道的時間很短 順序寫使硬盤盡可能的發生連續I/O,而不是隨機I/O

 

從硬件層面來看,Kafka的高性能體現在它的順序寫,因為Kafka寫消息是順序寫,這樣使硬盤盡可能的發生連續I/O

 

 

操作系統層面-零拷貝

 

零拷貝(Zero-copy)技術指在計算機執行操作時,CPU 不需要先將數據從一個內存區域復制到另一個內存區域,從而可以減少上下文切換以及 CPU 的拷貝時間。

mmap:將內核中讀緩沖區(read buffer)的地址與用戶空間的緩沖區(user buffer)進行映射。從而實現內核緩沖區與應用程序內存的共享,省去了將數據從內核讀緩沖區(read buffer)拷貝到用戶    緩沖區(user buffer)的過程。

sendfile:數據通過 DMA 拷貝到內核態 Buffer 后,直接通過 DMA 拷貝到 NIC Buffer,無需 CPU 拷貝。

 

不使用零拷貝一次文件寫入的過程:

 

 

零拷貝技術(mmap)下的寫數據:

  

                                        

 零拷貝技術(sendfile)下的讀數據:

 

從操作系統層面來看,Kafka的高性能體現在使用了零拷貝技術

 

七、Kafka的數據可靠性原理

副本機制

 

 副本:通常是指分布式系統在多台網絡互聯的機器上保存有相同的數據拷貝

好處:

  1、提供數據冗余 系統部分組件失效,系統依然能夠繼續運轉,因而增加了整體可用性以及數據持久性

  2、提供高伸縮性(需要支持讀寫分離) 支持橫向擴展,能夠通過增加機器的方式來提升讀性能,進而提高讀操作吞吐量。

  3、改善數據局部性(需要支持讀寫分離) 允許將數據放入與用戶地理位置相近的地方,從而降低系統延時。

 

備注:Kafka不支持讀寫分離

    基於領導者(Leader-based)的副本機制              有 3 台 Broker 的 Kafka 集群上的副本分布情況如下:

 

常見的副本復制數據方式:[commit指broker返回客戶端成功,commit前客戶端請求阻塞]

  同步復制:只有所有的follower把數據拿過去后才commit。

  異步復制:只要leader拿到數據立即commit,等follower慢慢去復制。

  半同步復制:折中方案,有一部分follower同步完成,便commit。【推薦】

一部分follower + leader 稱之為ISR(In-sync Replicas,同步中的副本)

 

 

ISR:In-sync Replicas,一種同步復制、異步復制的折中方案。即一種在性能與數據可靠性的折中方案。 指的是同步中的副本(含Leader),一個動態調整的集合,而非靜態不變的。

ISR不但代表一種機制,ISR同時也代表了一個集合(同步中的副本)

  AR:Assigned Repllicas,分區的所有副本集合

  ISR:In-Sync Replicas,所有與leader副本保持一定程度同步的副本(包括Leader)集合

  OSR:Out-Sync Relipcas,與leader副本同步滯后過多的follow副本的集合

AR = ISR + OSR

 

折中的副本數如何配置? (即“幾個副本同步完,算數據可靠?”)

  Topic配置項:min.insync.replicas=2【需要保證ISR中至少有多少個replica】

 

不滿足min.insync.replicas會怎么樣?

  當Producer配置acks=-1時,生產者會拋出分區不可用異常,不允許寫入(因為寫入會丟) 【使用此配置時,ISR有效】

  當Producer設置acks=1/0時,生產者不受影響【使用此配置時,ISR沒用】

 

“動態調整,非靜止不變”如何理解?

Broker配置:replica.lag.time.max.ms=10000 [最長容忍的不拉取數據的時間]

follower超過10秒沒有向leader發起fech請求:從ISR剔除(follower可能在fullGC、資源緊張等)

follower超過10秒又向leader發起fech請求:添加到ISR中

 

副本全部宕機,恢復策略:

  1、等待ISR中的任一個Replica“活”過來,並且選它作為Leader

  2、選擇第一個“活”過來的Replica(不一定是ISR中的)作為Leader

Topic配置:unclean.leader.election.enable=true代表第二種,fasle代表第一種

  v0.11默認false,之前默認true

如何選擇恢復策略?

 根據實際業務來選擇,如果對實時消息敏感的業務,選擇第一種,因為ISR中follower的消息最接近leader中的消息,如果對實時消息不敏感,就使用第二種,可以提高性能。

 

LEO(last end offset):日志末端偏移量,記錄了該副本對象底層日志文件中下一條消息的offset值。

HW(highwatermark):高水位值,ISR中最小的LEO為HW

 

 

 

 

 

灰色-已提交:小於HW值的所有消息被認為是“已備份的”,對consumer可見。

白色-未提交:大於等於HW值所有消息被認為是“未備份的”,對consumer不可見。

 

 

 

 

 

背景:生產者acks=-1,Topic的min.insync.replicas=2,此時ISR為<leader、follower1、follwer2>

異常情況:ISR中的follwer1完成同步m2,follower2未完成同步m2,此時leader宕機。

問:此時原follower2接管成為Leader,會導致什么問題?

 因為此時的HW為follower2的m1,若follower2接管為leader,則會導致follower1的m2消息無法被消費

 

八、Kafka的高可用原理

分區副本Leader選舉原理

  各自為政”的leader選舉(v0.8.2-)

    說明:每個Partition的多個Replica同時競爭Leader 原理:搶占創建Zookeeper的臨時節點,搶占成功則為Leader,否則注冊watch;若Leader宕機,觸發watch,再次搶占。

    優點:實現簡單

    缺點: 1、性能差(Zookeeper不適合頻繁寫) 2、Herd Effect(羊群效應)

 

 

 

  基於controller的leader選舉(v0.8.2+)

    說明:整個集群中選舉出一個Broker作為Controller,Controller為所有Partition指定Leader及Follower。

    優點:減輕Zookeeper負載

    缺點:引入Controller增加了復雜度,需要考慮Controller的Failover

 

 

 

 

Controller: 控制器,Apache Kafka的核心組件,在Apache Zookeeper的幫助下管理和協調控制整個Kafka集群。

  集群中的任意一台Broker都能充當Controller的角色。

  每個正常運行的Kafka集群,在任何時刻都有且只有一個Controller。

 選舉方式:Broker 在啟動時,會嘗試去 ZooKeeper 中創建 /controller 節點。第一個成功創建 /controller 節點的 Broker 會被指定為控制器。

 相關ZK節點

  /controller:臨時節點,記錄當前的Controller的brokerId以及選舉時間

  /controller_epoch:持久節點,記錄控制器發生變更的次數,即記錄當前的控制器是第幾代控制器。

controller_epoch的作用?  防止"腦裂"

 

背景:若Controller所在的Broker故障,則必須有新Controller繼續工作,但很難確定原Broker是宕機還是只是暫時的故障,若原Broker僅是假死,假死后,在原Controller眼里沒有任何變化,Broker甚至  不知道自己已經“下崗”了,此場景在分布式系統中,稱之為“腦裂”

解決辦法:當其他Broker知道當前的epoch number時,如果他們從Controller收到包含舊(較小)epoch number的消息,則它們將被忽略。

 

——面試題——

 

1、Kafka高性能的原理?

     從使用層面看,Kafka是多分區並行消費,同時壓縮數據和消息批量發送,節省了網絡IO開銷

  從存儲機制層面看,Kafka采用稀疏索引來寫數據,故不需要每次都寫索引文件;采用了分段存儲,讀取效率高,同時方便消息清理

  從硬件層面看,Kafka采用了順序寫的方式,將消息追加到分區的末尾,順序寫使硬盤盡可能的發生連續IO,而不是隨機IO

    從操作系統層面看,Kafka采用了零拷貝技術,加快了讀寫數據的速度。

 

2、Kafka的應用場景?

 異步處理、應用解耦、流量削峰、冗余數據、消息通訊

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM