kafka名詞說明
分佈式 高吞吐量 消息系統
producer:生產者
consumer:消費者
broker:機器,節點
controller:kafka服務器的主節點 負責管理元數據(zk存儲一份)
follower:kafka服務器的從節點 (同步元數據)
topic:主題。類似於關係型數據庫中的表
partition:一個主題可以有多個分區
replica:副本,爲了保證數據安全,每個partition可以設置多個副本(leader replica和slave replica)
message:消息 存放在partition裏
offset:偏移量 消費者的消費進度
NIO:同步非阻塞,服務器實現模式爲一個請求一個線程,即客戶端發送的連接請求都會註冊到多路複用器上,多路複用器輪詢到連接有I/O請求時才啓動一個線程進行處理
reactor
跳錶索引 空間換時間 加快消息所在文件查找
producer端高性能:批處理、內存池、封裝同一服務器請求
批處理是消息達到16K或者默認0ms發送一批次 batch.size linger.ms
consumer
同一消費者組內部是P2P模式,一個消息只能被同一個消費者組的一個消費者消費
不同組是發佈訂閱模式
0.10後偏移量存儲方式由zk改爲kafka自身的topic 名字爲__consumer_offsets-0到49默認50分區
zk不適合高併發
如何通過offset查找Message
例如,讀取offset=368776的Message,需要通過如下兩個步驟。
第一步:查找Segment File.
00000000000000000000.index表示最開始的文件,其實偏移量(offset)爲0;第二個文件00000000000000368769.index的其實偏移量爲368770(368769+1),依次類推。以其實偏移量命名並排序這些文件,只要根據offset**二分查找**文件列表,就可以快速定位到具體文件。
當offset=368776時,定位到00000000000000368769.index|log。
第二步:通過Segment File 查找Message。
通過第一步定位到Segment File,當offset=368776時,依次定位到00000000000000368769.index的元數據物理位置和00000000000000368769.log的物理偏移地址,然後再通過00000000000000368769.log順序查找,知道offset=368776爲止。
Segment Index File採取稀疏索引存儲方式,可以減少索引文件大小,通過Linux mmap接口可以直接進行內存操作。稀疏索引爲數據文件的每個對應Message設置一個元數據指針,它比稠密索引節省了更多的存儲空間,但查找起來需要消耗更多的時間。
kafka元數據刷新時間默認5min
生產者發送數據流程
消息封裝成ProducerRecord
序列化
消息計算分區(帶key爲hash,不帶爲輪詢;與broker通信獲取元數據信息)
將消息放到RecordAccumulator(緩存默認32M)
啓動一個Sender線程,去緩存中取消息,封裝成批次(默認16K)
該線程將批次數據發送到broker
RecordAccmulator 原理
ISR:副本同步隊列
AR:所有副本
isr由leader負責維護,follower從leader同步數據有一定的延遲,如果某個follower超過該閾值沒有完成同步,leader就會把該follower從isr中剔除,放到osr中,
osr+isr = ar
kafka中的broker 是幹什麼的
broker 是消息的代理,Producers往Brokers裏面的指定Topic中寫消息,Consumers從Brokers裏面拉取指定Topic的消息,然後進行業務處理,broker在中間起到一個代理保存消息的中轉站。
producer如何優化速度:
增加線程
提高 batch.size
增加更多 producer 實例
增加 partition 數
設置 acks=-1 時,如果延遲增大:可以增大 num.replica.fetchers(follower 同步數據的線程數)來調解;
跨數據中心的傳輸:增加 socket 緩衝區設置以及 OS tcp 緩衝區設置。
消費者分區分配策略
range
range策略是基於每個主題的 對於每個主題,我們以數字順序排列可用分區,以字典順序排列消費者。然後,將分區數量除以消費者總數,以確定分配給每個消費者的分區數量。如果沒有平均劃分(PS:除不盡),那麼最初的幾個消費者將有一個額外的分區。
輪詢
輪詢分配策略是基於所有可用的消費者和所有可用的分區的
與前面的range策略最大的不同就是它不再侷限於某個主題
如果所有的消費者實例的訂閱都是相同的,那麼這樣最好了,可用統一分配,均衡分配
丟數據場景:
ack=0 沒有消息確認,
ack=1 leader收到消息即發送ack,此時如果isr中的follower還沒同步leader,leader就出問題,這部分數據就回丟失
ack=-1 等待所有follower同步完數據後,再發送ack,延時高,數據安全性最高,也會出現丟失數據的情況:如果isr中只有leader一臺機器時,相當於ack=1的時候
另一個是使用高級消費者的時候消費者讀完數據就提交offset,但數據還沒處理完就掛掉了,此時重新啓動後上一部分數據就不能再消費(使用低級消費者)
數據重複場景:
cks = -1 的情況下,數據發送到 leader 後 ,部分 ISR 的副本同步,leader 此時掛掉。比如 follower1 和 follower2 都有可能變成新的 leader, producer 端會得到返回異常,producer 端會重新發送數據,數據可能會重複
另外, 在高階消費者中,offset 採用自動提交的方式, 自動提交時,假設 1s 提交一次 offset 的更新,設當前 offset = 10,當消費者消費了 0.5s 的數據,offset 移動了 15,由於提交間隔爲 1s,因此這一 offset 的更新並不會被提交,這時候我們寫的消費者掛掉,重啓後,消費者會去 ZooKeeper 上獲取讀取位置,獲取到的 offset 仍爲10,它就會重複消費. 解決辦法使用低級消費者
Kafka中是怎麼體現消息順序性的?
kafka每個partition中的消息在寫入時都是有序的,消費時,每個partition只能被每一個group中的一個消費者消費,保證了消費時也是有序的。
整個topic不保證有序。如果爲了保證topic整個有序,那麼將partition調整爲1.
KAFKA速度快的原因:
直接使用linux的cache高效緩存數據
順序寫磁盤 減少尋址
使用零拷貝 傳統的數據發送需要發送四次上下切換,採用sendfile系統調用後,數據直接在內核態轉換,系統上下文切換變成2次
數據傳輸的事物定義有哪三種?
數據傳輸的事務定義通常有以下三種級別:
(1)最多一次: 消息不會被重複發送,最多被傳輸一次,但也有可能一次不傳輸
(2)最少一次: 消息不會被漏發送,最少被傳輸一次,但也有可能被重複傳輸.
(3)精確的一次(Exactly once): 不會漏傳輸也不會重複傳輸,每個消息都傳輸被一次而
且僅僅被傳輸一次,這是大家所期望的
Kafka 判斷一個節點是否還活着有那兩個條件?
(1)節點必須可以維護和 ZooKeeper 的連接,Zookeeper 通過心跳機制檢查每個節點的連
接
(2)如果節點是個 follower,他必須能及時的同步 leader 的寫操作,延時不能太久
producer 是否直接將數據發送到 broker 的 leader(主節點)?
producer 直接將數據發送到 broker 的 leader(主節點),不需要在多個節點進行分發,爲了
幫助 producer 做到這點,所有的 Kafka 節點都可以及時的告知:哪些節點是活動的,目標
topic 目標分區的 leader 在哪。這樣 producer 就可以直接將消息發送到目的地了
Kafa consumer 是否可以消費指定分區消息?
Kafa consumer 消費消息時,向 broker 發出"fetch"請求去消費特定分區的消息,consumer
指定消息在日誌中的偏移量(offset),就可以消費從這個位置開始的消息,customer 擁有
了 offset 的控制權,可以向後回滾去重新消費之前的消息,這是很有意義的
Kafka 消息是採用 Pull 模式,還是 Push 模式?
producer 將消息推送到 broker,consumer 從 broker 拉取消息
Kafka 存儲在硬盤上的消息格式是什麼?
消息由一個固定長度的頭部和可變長度的字節數組組成。頭部包含了一個版本號和 CRC32
校驗碼。
消息長度: 4 bytes (value: 1+4+n)
版本號: 1 byte
CRC 校驗碼: 4 bytes
具體的消息: n bytes
Kafka 與傳統消息系統之間有三個關鍵區別
(1).Kafka 持久化日誌,這些日誌可以被重複讀取和無限期保留
(2).Kafka 是一個分佈式系統:它以集羣的方式運行,可以靈活伸縮,在內部通過複製數據
提升容錯能力和高可用性
(3).Kafka 支持實時的流式處理
Kafka 高效文件存儲設計特點:
(1).Kafka 把 topic 中一個 parition 大文件分成多個小文件段,通過多個小文件段,就容易定
期清除或刪除已經消費完文件,減少磁盤佔用。
(2).通過索引信息可以快速定位 message 和確定 response 的最大大小。
(3).通過 index 元數據全部映射到 memory,可以避免 segment file 的 IO 磁盤操作。
(4).通過索引文件稀疏存儲,可以大幅降低 index 文件元數據佔用空間大小
Kafka 新建的分區會在哪個目錄下創建
在啓動 Kafka 集羣之前,我們需要配置好 log.dirs 參數,其值是 Kafka 數據的存放目錄,
這個參數可以配置多個目錄,目錄之間使用逗號分隔,通常這些目錄是分佈在不同的磁盤
上用於提高讀寫性能。
當然我們也可以配置 log.dir 參數,含義一樣。只需要設置其中一個即可。
如果 log.dirs 參數只配置了一個目錄,那麼分配到各個 Broker 上的分區肯定只能在這個
目錄下創建文件夾用於存放數據。
但是如果 log.dirs 參數配置了多個目錄,那麼 Kafka 會在哪個文件夾中創建分區目錄呢?
答案是:Kafka 會在含有分區目錄最少的文件夾中創建新的分區目錄,分區目錄名爲 Topic
名+分區 ID。注意,是分區文件夾總數最少的目錄,而不是磁盤使用量最少的目錄!也就
是說,如果你給 log.dirs 參數新增了一個新的磁盤,新的分區目錄肯定是先在這個新的磁
盤上創建直到這個新的磁盤目錄擁有的分區目錄不是最少爲止。
partition 的數據如何保存到硬盤
topic 中的多個 partition 以文件夾的形式保存到 broker,每個分區序號從 0 遞增,
且消息有序
Partition 文件下有多個 segment(xxx.index,xxx.log)
segment 文件裏的 大小和配置文件大小一致可以根據要求修改 默認爲 1g
如果大小大於 1g 時,會滾動一個新的 segment 並且以上一個 segment 最後一條消息的偏移
量命名
消費者負載均衡策略
一個消費者組中的一個分片對應一個消費者成員,他能保證每個消費者成員都能訪問,如
果組中成員太多會有空閒的成員
kafaka 生產數據時數據的分組策略
生產者決定數據產生到集羣的哪個 partition 中
每一條消息都是以(key,value)格式
Key 是由生產者發送數據傳入
所以生產者(key)決定了數據產生到集羣的哪個 partition