深入分析Kafka架構(一):工作流程、存儲機制、分區策略

一、前言

在開始之前首先要明確一點,kafka是一個分佈式流平臺,本質上是一個消息隊列。談到消息隊列,就會聯想到消息隊列的三大作用:異步、消峯、解耦。kafka主要應用在大數據的實時處理領域,使用起來比較簡單,本文主要分析kafka的工作流程、存儲機制,分區策略,並圍繞多個角度展開總結。

但是要注意的是,隨着時代的巨輪駛向2020,目前kafka已經不是一家獨大了,Pulsar作爲一個天生支持多租戶、跨地域複製、統一消息模型的消息平臺,已經在不少企業成功的替代了Kafka。關於Apache Pulsar的更多知識,感興趣的可以關注我,後面會對它進行總結和深入。

二、kafka工作流程

工作流程

  1. kafka將消息按照topic進行分類,每條message由三個屬性組成。
    • offset:表示 message 在當前 Partition 中的偏移量,是一個邏輯上的值,唯一確定了 Partition 中的一條 message,可以簡單的認爲是一個 id;
    • MessageSize:表示 message 內容 data 的大小;
    • data:message 的具體內容
  2. 在整個kafka架構中,生產者和消費者採用發佈和訂閱的模式,生產者生產消息,消費者消費消息,它倆各司其職,並且都是面向topic的。(需要注意:topic是邏輯上的概念,而partition是物理上的概念,每個partition對應於一個log文件,該log文件中存儲的就是producer生產的數據。
  3. Producer生產的數據會被不斷追加到該log文件末端,且每條數據都有自己的offset。
  4. 消費者組中的每個消費者,都會實時記錄自己消費到了哪個offset,這樣當出現故障並恢復後,可以從這個offset位置繼續進行消費,避免漏掉數據或者重複消費。

二、文件存儲機制

2.1、文件存儲結構及命名規則

在kafka的設計之初,考慮到了生產者生產的消息不斷追加到log文件末尾後導致log文件過大的情況,所以採用了分片索引機制,具體來說就是將每個partition分爲多個segment。每個segment對應三個文件:.index 文件、.log 文件、.timeindex 文件(早期版本中沒有)。其中**.log和.index**文件位於一個文件夾下,該文件夾的命名規則爲:topic名稱+分區序號。例如,csdn這個topic有2個分區,則其對應的文件夾爲csdn-0,csdn-1;

如果我們打開csdn-0這個文件夾,會看到裏面的文件如下:

00000000000000000000.index
00000000000000000000.log
00000000000000150320.index
00000000000000150320.log

通過這個文件夾下有兩個log,我們可以得出結論,這個partition有2個segment。

文件命名規則:partition全局的第一個segment從0開始,後續每個segment文件名爲上一個segment文件最後一條消息的offset值,數值大小爲64位,20位數字字符長度,沒有數字用0填充。

注意:index 文件並不是從0開始,也不是每次遞增1的,這是因爲 Kafka 採取稀疏索引存儲的方式,每隔一定字節的數據建立一條索引,它減少了索引文件大小,使得能夠把 index 映射到內存,降低了查詢時的磁盤 IO 開銷,同時也並沒有給查詢帶來太多的時間消耗。

下面引用一張舊的kafka存儲機制圖,不帶.timeindex 文件:
存儲機制

2.2、文件關係

index文件和log文件的關係:“.index”文件存儲大量的索引信息,“.log”文件存儲大量的數據,索引文件中的元數據指向對應數據文件中message的物理偏移地址。
文件關係

2.3、使用offset查找message

因爲每一個segment文件名爲上一個 Segment 最後一條消息的 offset ,所以當需要查找一個指定 offset 的 message 時,通過在所有 segment 的文件名中進行二分查找就能找到它歸屬的 segment ,再在其 index 文件中找到其對應到文件上的物理位置,就能拿出該 message 。

舉例:這裏我們以查找offset爲6的message爲例,查找流程如下:

  1. 首先要確定這個offset信息在哪個segment文件(由於是順序讀寫,這裏使用二分查找法),第一個文件名爲00000000000000000000,第二個爲00000000000000150320,所以6這個offset的數據肯定在第一個文件裏面;
  2. 找到文件後就好辦了,在這個文件的 00000000000000000000.index文件中的[6,9807]定位到00000000000000000000.log文件中9807這個位置來進行數據讀取即可。

三、分區策略

3.1、爲什麼要進行分區

在瞭解分區策略之前需要先了解爲什麼要分區,可以從兩方面來解釋這個問題:

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

首先要知道producer發送的數據其實需要封裝成一個ProducerRecord對象纔可以,我們看ProducerRecord提供的方法如下:

ProducerRecord構造函數
通過這個構造方法,我們知道kafka分區策略有如下3種:

  1. 指明 partition 的情況下,直接將指明的值直接作爲 partiton 值;
  2. 沒有指明 partition 值但有 key 的情況下,將 key 的 hash 值與 topic 的 partition 數進行取餘得到 partition 值;
  3. 既沒有 partition 值又沒有 key 值的情況下,第一次調用時隨機生成一個整數(後面每次調用在這個整數上自增),將這個值與 topic 可用的 partition 總數取餘得到 partition 值,也就是常說的 round-robin 算法。

四、總結

通過本文,我們探討了kafka的工作流程、存儲機制,分區策略,相信已經理清楚了生產者生產的數據是怎麼存儲的以及怎麼根據offset去查詢數據這類問題。下一篇將重點分析這部分數據是怎麼保證可靠性的,以及kafka的故障處理細節。

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