Kafka

一. Kafka 概述

1.1 定義

Kafka 是一個分佈式的基於發佈/訂閱模式消息隊列(Message Queue),主要應用於大數據實時處理領域。

1.2 消息隊列

1.2.1 傳統消息隊列的應用場景
在這裏插入圖片描述
使用消息隊列的好處:異步,消峯,解耦

1.2.2 消息隊列的

(1 )點對點模式(一對一,消費者主動拉取數據,消息收到後消息清除)

消息生產者生產消息發送到Queue中,然後消息消費者從Queue中取出並且消費消息。
消息被消費以後,queue 中不再有存儲,所以消息消費者不可能消費到已經被消費的消息。Queue 支持存在多個消費者,但是對一個消息而言,只會有一個消費者可以消費。
在這裏插入圖片描述
(2 )發佈/ 訂閱模式(一對多,消費者消費數據之後不會清除消息)

消息生產者(發佈)將消息發佈到 topic 中,同時有多個消息消費者(訂閱)消費該消
息。和點對點方式不同,發佈到 topic 的消息會被所有訂閱者消費。
在這裏插入圖片描述

1.3 Kafka 基礎架構

在這裏插入圖片描述
生產者,消費者,kafka集羣,zk 四大塊;
kafka直接向zk註冊,zk會自動創建一個kafka集羣;kafka想要集成集羣,只要他們用同一個zk就可以組成了;
zk存消費者的offset,0.9版本之後保存到kafka集羣內部了;和zk交互太過頻繁,所以改了

1 ) Producer :消息生產者,就是向 kafka broker 發消息的客戶端;

2 ) Consumer :消息消費者,向 kafka broker 取消息的客戶端;

3 ) Consumer Group (CG ):消費者組,由多個 consumer 組成。 消費者組內每個消費者負責消費不同分區的數據,一個分區只能由一個 組內 消費者消費;消費者組之間互不影響,所有的消費者都屬於某個消費者組,即 消費者組是邏輯上的一個訂閱者。消費者組就是一個消費團體

4 ) Broker :一臺 kafka 服務器就是一個 broker。一個集羣由多個 broker 組成。一個 broker可以容納多個 topic。

5 ) Topic :可以理解爲一個隊列, 生產者和消費者面向的都是一個 topic;
主題是分區的,是有副本的;

6 ) Partition :爲了實現擴展性,一個非常大的 topic 可以分佈到多個 broker(即服務器)上,一個 topic 可以分爲多個 partition,每個 partition 是一個有序的隊列;某一個分區只能被某一個消費者組裏面的一個消費者消費,消費者組看做是一個大的消費體;分區策略提高某一個topic的負載能力,提高讀寫併發度;

7) ) Replica: :副本,爲保證集羣中的某個節點發生故障時,該節點上的partition 數據不丟失,且 kafka 仍然能夠繼續工作,kafka 提供了副本機制,一個 topic 的每個分區都有若干個副本,一個 leader 和若干個 follower。

8 ) leader :每個分區多個副本的“主”,生產者發送數據的對象,以及消費者消費數據的對象都是 leader。生產者消費者是直接面向leader的

9 ) follower :每個分區多個副本中的“從”,實時從 leader 中同步數據,保持和 leader 數據的同步。leader 發生故障時,某個 follower 會成爲新的 follower。僅僅是備份的作用,不提供讀寫能力,請求直接訪問leader的;

二: Kafka 快速入門

mv kafka_2.11-0.11.0.0/ kafka
mkdir logs
cd config/
bin/kafka-server-start.sh  -daemon config/server.properties
#broker 的全局唯一編號,不能重複
broker.id=0
#刪除 topic 功能使能
delete.topic.enable=true
#處理網絡請求的線程數量
num.network.threads=3
#用來處理磁盤 IO 的現成數量
num.io.threads=8
#發送套接字的緩衝區大小
socket.send.buffer.bytes=102400
#接收套接字的緩衝區大小
socket.receive.buffer.bytes=102400
#請求套接字的緩衝區大小
socket.request.max.bytes=104857600
#kafka 運行日誌存放的路徑,這裏是存放日誌和數據一起了,可以設置數據日誌分離
log.dirs=/opt/module/kafka/logs
#topic 在當前 broker 上的分區個數
num.partitions=1
#用來恢復和清理 data 下數據的線程數量
num.recovery.threads.per.data.dir=1
#segment 文件保留的最長時間,超時將被刪除
log.retention.hours=168
#配置連接 Zookeeper 集羣地址
zookeeper.connect=localhost:2181
bin/kafka-console-consumer.sh --zookeeper hadoop:2181 --topic first
bin/kafka-console-consumer.sh --bootstrap-server hadoop:9092 --topic first
消費者連接2種方式:
--zookeeper 是連接zk,0.9版本之前命令,offset存放在zk裏面,以 消費者組+主題+分區 爲存放offset位置偏移量信息
--bootstrap-server  連接kafka集羣,0.9版本之後命令 默認50分區一個副本

三:Kafka 架構深入

3.1 Kafka 工作流程及文件存儲機制

Kafka 工作流程
在這裏插入圖片描述
Kafka 中消息是以 topic 進行分類的,生產者生產消息,消費者消費消息,都是面向 topic的。

topic 是邏輯上的概念,而 partition 是物理上的概念,每個 partition 對應於一個 log 文件,該 log 文件中存儲的就是 producer 生產的數據。Producer 生產的數據會被不斷追加到該log 文件末端,且每條數據都有自己的 offset。消費者組中的每個消費者,都會實時記錄自己消費到了哪個 offset,以便出錯恢復時,從上次的位置繼續消費。

Kafka文件存儲機制
在這裏插入圖片描述

由於生產者生產的消息會不斷追加到 log 文件末尾,爲防止 log 文件過大導致數據定位效率低下,Kafka 採取了 分片 和 索引 機制,將每個 partition 分爲多個 segment。每個 segment 對應兩個文件——“.index”文件和“.log”文件。這些文件位於一個文件夾下,該文件夾的命名,默認1GB就會生成一個segment 分片;

規則爲:topic 名稱+分區序號。例如,first 這個 topic 有三個分區,則其對應的文件夾爲 first-0,first-1,first-2。

00000000000000000000.index
00000000000000000000.log
00000000000000170410.index
00000000000000170410.log
00000000000000239430.index
00000000000000239430.log

在這裏插入圖片描述
index 和 log 文件以當前 segment 的第一條消息的 offset 命名。下圖爲 index 文件和 log文件的結構示意圖。

index文件和log文件詳解:
在這裏插入圖片描述
.index”文件存儲大量的索引信息,“.log”文件存儲大量的數據,索引文件中的元數據指向對應數據文件中 message 的物理偏移地址。

3.2 Kafka 生產者

3.2.1 分區策略

1 )分區的原因

  • 方便在集羣中擴展,每個 Partition 可以通過調整以適應它所在的機器,而一個 topic又可以有多個 Partition 組成,因此整個集羣就可以適應任意大小的數據了;
  • 可以提高併發,因爲可以以 Partition 爲單位讀寫了。

2 ) 分區的原則
我們需要將 producer 發送的數據封裝成一個 ProducerRecord 對象。
3.2.2 數據可靠性保證

爲保證 producer 發送的數據,能可靠的發送到指定的 topic,topic 的每個 partition 收到producer 發送的數據後,都需要向 producer 發送 ack(acknowledgement 確認收到),如果 producer 收到 ack,就會進行下一輪的發送,否則重新發送數據。
在這裏插入圖片描述
1 ) 副本數據同步策略
在這裏插入圖片描述
2 )ISR

採用第二種方案之後,設想以下情景:leader 收到數據,所有 follower 都開始同步數據,但有一個 follower,因爲某種故障,遲遲不能與 leader 進行同步,那 leader 就要一直等下去,直到它完成同步,才能發送 ack。這個問題怎麼解決呢?

解決:
Leader 維護了一個動態的 in-sync replica set (ISR),意爲和 leader 保持同步的 follower 集合。當 ISR 中的 follower 完成數據的同步之後,leader 就會給 producer 發送 ack。如果 follower 長 時 間 未 向 leader 同 步 數 據 , 則 該 follower 將 被 踢 出 ISR , 該 時 間 閾 值 由 replica.lag.time.max.ms 參數設定。Leader 發生故障之後,就會從 ISR 中選舉新的 leader。

3 )ack 應答機制

對於某些不太重要的數據,對數據的可靠性要求不是很高,能夠容忍數據的少量丟失,所以沒必要等 ISR 中的 follower 全部接收成功。

所以 Kafka 爲用戶提供了三種可靠性級別,用戶根據對可靠性和延遲的要求進行權衡,選擇以下的配置。

acks 參數配置:

acks:

0:producer 不等待 broker 的 ack,這一操作提供了一個最低的延遲,broker 一接收到還沒有寫入磁盤就已經返回,當 broker 故障時有可能 丟失數據

1:producer 等待 broker 的 ack,partition 的 leader 落盤成功後返回 ack,如果在 follower 同步成功之前 leader 故障,那麼將會 丟失數據

acks = 1 數據丟失案例
在這裏插入圖片描述
-1(all):producer 等待 broker 的 ack,partition 的 leader 和 follower(ISR中的) 全部落盤成功後才返回 ack。但是如果在 follower 同步完成後,broker 發送 ack 之前,leader 發生故障,那麼會造成 數據重複,也就是leader和follower持久化了該消息,但是在發送ack之前掛了的情況;

注意,這裏當isr同步的follwer集合裏面由於某些網絡原因沒有了一個follower的時候,這種情況就退化到了ack = 1的情況了,也就會發生丟失數據

acks = -1 數據重複案例
在這裏插入圖片描述

4 ) 故障處理細節

場景:假設在數據同步的時候,leader自己同步了19條信息,follower1 同步了12條信息,follower2同步了15條信息,這個時候leader掛掉了,這個時候需要從isr集合中選取一個作爲leader,由於各自同步的數據不一樣,對消費者可能產生消費數據不一致的情況,通過 HW 和 LEO 就可以保證副本之間的數據一致性問題;多退少補…

Log文件中的HW和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同步數據。

注意:這隻能保證副本之間的數據一致性,並不能保證數據不丟失或者不重複。

3.2.3 Exactly Once 語義
在這裏插入圖片描述

3.3 Kafka 消費者

3.3.1 消費 方式

consumer 採用 pull(拉)模式從 broker 中讀取數據。
push (推)模式很難適應消費速率不同的消費者,因爲消息發送速率是由 broker 決定的。

它的目標是儘可能以最快速度傳遞消息,但是這樣很容易造成 consumer 來不及處理消息,典型的表現就是拒絕服務以及網絡擁塞。而 pull 模式則可以根據 consumer 的消費能力以適當的速率消費消息。

pull 模式不足之處是,如果 kafka 沒有數據,消費者可能會陷入循環中,一直返回空數據。針對這一點,Kafka 的消費者在消費數據時會傳入一個時長參數 timeout,如果當前沒有數據可供消費,consumer 會等待一段時間之後再返回,這段時長即爲 timeout。

3.3.2 分區分配策略

一個 consumer group 中有多個 consumer,一個 topic 有多個 partition,所以必然會涉及到 partition 的分配問題,即確定那個 partition 由哪個 consumer 來消費。

Kafka 有兩種分配策略,一是 RoundRobin(面向組的),一是 Range(面向主題的)。

1 )RoundRobin

分區分配策略之RoundRobin,按照group組來分的,面向組的
在這裏插入圖片描述
輪詢,差值最多差一個,不會導致消費者消費分區數的不均衡;但是當消費者組的消費者消費的主題不一致時會出問題;
在這裏插入圖片描述
存在問題:
在這裏插入圖片描述
這種策略情況下,會把2個主題當做一個整體來看,封裝成一個類,包含分區和主題,進行hash,排序,然後在進行輪詢;它把消費者組訂閱的主題全當做一個整理來看,這樣會導致消費者B就會消費到T1主題的是消息了

這策略前提條件是:當前消費者組裏面的消費者訂閱的主題是一樣的時候,否則會出問題;

2 )Range

分區分配策略之Range 按照topic主題來分的,面向主題的
在這裏插入圖片描述
7/3=2餘1,分爲3,2,2 ;可能帶來消費者消費的不對等問題
在這裏插入圖片描述
A訂閱T1主題,B訂閱T2主題,AB都屬於同一個消費者組,按照主題來分的,主題1有3個分區,有2個訂閱者,前2個給A消費者,後一個給B消費者;同樣,T2也是這樣分配,這樣就會導致消費者A消費了4個分區,消費者B消費了2個分區,分配不均衡問題;

分區分配策略觸發時機: 消費者的個數發生變化時都會觸發分配策略,重新分配,即增加或者減少消費者的個數都會觸發;

3.3.3 offset 的維護
由於 consumer 在消費過程中可能會出現斷電宕機等故障,consumer 恢復後,需要從故障前的位置的繼續消費,所以 consumer 需要實時記錄自己消費到了哪個 offset,以便故障恢復後繼續消費。 G(組) + T(主題) + P(分區) 確定offset位置
在這裏插入圖片描述
Kafka 0.9 版本之前,consumer 默認將 offset 保存在 Zookeeper 中
在這裏插入圖片描述
從 0.9 版本開始,consumer 默認將 offset 保存在 Kafka 一個內置的 topic 中,該 topic 爲__consumer_offsets。

查看:
1)修改配置文件 consumer.properties

    添加屬性   exclude.internal.topics=false

2)讀取 offset

0.11.0.0 之前版本:
在這裏插入圖片描述
0.11.0.0 之後版本(含):
在這裏插入圖片描述
在這裏插入圖片描述

根據G + T + P 來記錄offset,這樣即使某個消費者宕機後相同組裏面的消費者可以繼續接着消費。

3.3.4 消費者組案例
在這裏插入圖片描述

3.4 Kafka 高效 讀寫 數據

1 )順序寫磁盤(單機+集羣)
Kafka 的 producer 生產數據,要寫入到 log 文件中,寫的過程是一直追加到文件末端,爲順序寫。官網有數據表明,同樣的磁盤,順序寫能到 600M/s,而隨機寫只有 100K/s。這與磁盤的機械機構有關,順序寫之所以快,是因爲其省去了大量磁頭尋址的時間。

2 )零複製技術(單機+集羣)
在這裏插入圖片描述
3 )topic分區機制(集羣)

3.5 Zookeeper 在 Kafka 中的作用

在這裏插入圖片描述
Leader選舉流程
在這裏插入圖片描述

3.6 Kafka 事務

Kafka 從 0.11 版本開始引入了事務支持。事務可以保證 Kafka 在 Exactly Once 語義的基礎上,生產和消費可以跨分區和會話,要麼全部成功,要麼全部失敗。

場景:生產者向 topic 0,1,2 三個分區發送10,10,10 各10條數據,當發送給第三個分區的時候生產者就掛了;當生產者重啓的時候應該把這30條數據重新發送一次,但是重新啓動之後PID就變了,這樣發送0,和1號分區的10條數據就重複發送了,2號分區不會出現重複的情況;這種情況是不能實現跨分區跨會話的冪等性的;下面解決Producer事務問題。
在這裏插入圖片描述

四:Kafka API

4.1 Producer API

4.1.1 消息發送流程
Kafka 的 Producer 發送消息採用的是 異步發送 的方式。在消息發送的過程中,涉及到了兩個線程 ——main 線程和 Sender 線程,以及 一個線程共享變量 ——RecordAccumulator。main 線程將消息發送給 RecordAccumulator,Sender 線程不斷從 RecordAccumulator 中拉取消息發送到 Kafka broker。

KafkaProducer 發送消息流程
在這裏插入圖片描述
相關參數:

batch.size :只有數據積累到 batch.size 之後,sender 纔會發送數據。
linger.ms :如果數據遲遲未達到 batch.size,sender 等待 linger.time 之後就會發送數據。

4.1.2 異步 發送 API

需要用到的類:
KafkaProducer:需要創建一個生產者對象,用來發送數據
ProducerConfig:獲取所需的一系列配置參數
ProducerRecord:每條數據都要封裝成一個 ProducerRecord 對象

  1. 不帶回調函數的 API
  2. 帶回調函數的 API

回調函數會在 producer 收到 ack 時調用,爲異步調用,該方法有兩個參數,分別是RecordMetadata 和 Exception,如果 Exception 爲 null,說明消息發送成功,如果Exception 不爲 null,說明消息發送失敗。

注意:消息發送失敗會自動重試,不需要我們在回調函數中手動重試。

4.1.3 同步發送 API

同步發送的意思就是,一條消息發送之後,會阻塞當前線程,直至返回 ack。由於 send 方法返回的是一個 Future 對象,根據 Futrue 對象的特點,我們也可以實現同步發送的效果,只需在調用 Future 對象的 get 方發即可。

4.1.4 自定義分區的生產者
在這裏插入圖片描述

4.2 Consumer API

Consumer 消費數據時的可靠性是很容易保證的,因爲數據在 Kafka 中是持久化的,故不用擔心數據丟失問題。

由於 consumer 在消費過程中可能會出現斷電宕機等故障,consumer 恢復後,需要從故障前的位置的繼續消費,所以 consumer 需要實時記錄自己消費到了哪個 offset,以便故障恢復後繼續消費。

所以 offset 的維護是 Consumer 消費數據是必須考慮的問題

4.2.1 自動提交 offset

需要用到的類:
KafkaConsumer:需要創建一個消費者對象,用來消費數據
ConsumerConfig:獲取所需的一系列配置參數
ConsuemrRecord:每條數據都要封裝成一個 ConsumerRecord 對象

爲了使我們能夠專注於自己的業務邏輯,Kafka 提供了自動提交 offset 的功能。
自動提交 offset 的相關參數:
enable.auto.commit :是否開啓自動提交 offset 功能
auto.commit.interval.ms :自動提交 offset 的時間間隔
在這裏插入圖片描述

4.2.2 手動 提交 offset

雖然自動提交 offset 十分簡介便利,但由於其是基於時間提交的,開發人員難以把握offset 提交的時機。因此 Kafka 還提供了手動提交 offset 的 API。

手動提交 offset 的方法有兩種:分別是 commitSync(同步提交)和 commitAsync(異步提交)。兩者的相同點是,都會將次 本次 poll 的一批數據最高的偏移量提交;不同點是,commitSync 阻塞當前線程,一直到提交成功,並且會自動失敗重試(由不可控因素導致,也會出現提交失敗);而 commitAsync 則沒有失敗重試機制,故有可能提交失敗。

1 ) 同步提交 offset
在這裏插入圖片描述
在這裏插入圖片描述
2 )異步提交 offset

雖然同步提交 offset 更可靠一些,但是由於其會阻塞當前線程,直到提交成功。因此吞吐量會收到很大的影響。因此更多的情況下,會選用異步提交 offset 的方式。
在這裏插入圖片描述
3 ) 數據漏消費和重複消費分析

無論是同步提交還是異步提交 offset,都有可能會造成數據的漏消費或者重複消費。先提交 offset 後消費,如果消費消息發生異常,則這條消息就沒有被完成消費掉,就有可能造成數據的漏消費;
而先消費後提交 offset,假如在提交offset的時候發生異常,那麼在kafka或者zk上面維護的offset位置偏移就不會發生改變,下次消費就有會造成數據的重複消費。

當需要從新消費數據的時候可以重置offset的偏移量
在這裏插入圖片描述
可以從官網查看參數默認值及含義:
在這裏插入圖片描述
4.2.3 自定義存儲 offset
在這裏插入圖片描述
在這裏插入圖片描述

4.3 自定義 Interceptor

在這裏插入圖片描述
是捕獲每個 interceptor 可能拋出的異常記錄到錯誤日誌中而非在向上傳遞。這在使用過程中
要特別留意。

4.3.2 攔截器案例
1)需求:
實現一個簡單的雙 interceptor 組成的攔截鏈。第一個 interceptor 會在消息發送前將時間戳信息加到消息 value 的最前部;第二個 interceptor 會在消息發送後更新成功發送消息數或失敗發送消息數
2)案例實操

五: Kafka 監控

Kafka Eagle
在這裏插入圖片描述

六:Kafka 面試題

面試問題

1. Kafka 中的 ISR(InSyncRepli)、OSR(OutSyncRepli)、AR(AllRepli)代表什麼?
ISR(InSyncRepli) + OSR(OutSyncRepli) = AR(AllRepli)

2. Kafka 中的 HW、LEO 等分別代表什麼?
HW:消費者可見的最大offset;
LEO:每一個分區裏面多個副本都有一個自己最大的offset值;

3. Kafka 中是怎麼體現消息順序性的?
某個分區內有序,各分區之間是無序的;

4. Kafka 中的分區器、序列化器、攔截器是否瞭解?它們之間的處理順序是什麼?
見 4.1.1 消息發送流程

5. Kafka 生產者客戶端的整體結構是什麼樣子的?使用了幾個線程來處理?分別是什麼?
見 4.1.1 消息發送流程;RecordAccumulator 數據時已經分好區的數據; 2個

6. “消費組中的消費者個數如果超過 topic 的分區,那麼就會有消費者消費不到數據”這句話是否正確?
正確

7. 消費者提交消費位移時提交的是當前消費到的最新消息的 offset 還是 offset+1?
offset+1

8. 有哪些情形會造成重複消費?
先處理數據,再提交offset

9. 那些情景會造成消息漏消費?
先提交offset,再處理數據

10. 當你使用 kafka-topics.sh 創建(刪除)了一個 topic 之後,Kafka 背後會執行什麼邏輯?
1)會在 zookeeper 中的/brokers/topics 節點下創建一個新的 topic 節點,如:
/brokers/topics/first
2)觸發 Controller 的監聽程序
3)kafka Controller 負責 topic 的創建工作,並更新 metadata cache

11. topic 的分區數可不可以增加?如果可以怎麼增加?如果不可以,那又是爲什麼?
可增不可減,增可以,減的話已經存在分區內的數據沒法處理

12. topic 的分區數可不可以減少?如果可以怎麼減少?如果不可以,那又是爲什麼?
可增不可減,增可以,減的話已經存在分區內的數據沒法處理

13. Kafka 有內部的 topic 嗎?如果有是什麼?有什麼所用?
有,__ConsumerOffsets;給普通的消費者存offset用的

14. Kafka 分區分配的概念?
2種策略,見 3.3.2 分區 分配策略

15. 簡述 Kafka 的日誌目錄結構?
.index .log 二分查找法

16. 如果我指定了一個 offset,Kafka Controller 怎麼查找到對應的消息?

17. 聊一聊 Kafka Controller 的作用?
臨時選的老大,元數據之類的

18. Kafka 中有那些地方需要選舉?這些地方的選舉策略又有哪些?
Controller 和 leader(ISR) 選舉

19. 失效副本是指什麼?有那些應對措施?

20. Kafka 的哪些設計讓它有如此高的性能
分佈式,順序寫磁盤,零拷貝

Kafka史上最詳細原理總結
Kafka-高性能的分佈式消息隊列
Kafka

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章