Kafka 架構分析(1)

本次kafka相關分析總結,以apache kafka爲準。

地址:http://kafka.apache.org/documentation/

中文文檔地址:https://kafka.apachecn.org/

瞭解kafka需要先了解以下幾個基本概念:

名稱 說明
Broker kafka作爲中件,幫我們存儲和轉發消息,所以我們把kafkar的服務叫做Broker。
Record(消息) 客戶端之間傳輸的數據
Topic 生產者與消費者關聯的途徑,可以理解爲其他消息中間件的隊列
Producer 發送消息的生產者
Consumer 接收消息的消費者
Partition與Cluster topic分區
Segment partition再做一個切分,切分出來的單位叫段(segment)
Consumer Group 消費組
Consumer Offset 消費偏移量

Broker

Brokder :kafka做爲一箇中間件,是幫我們存儲和轉發消息的,它做的事有點像中介,所以我們把kafka的服務叫Broker。生產者和消費者都需要跟這個Broker建立一個連接,纔可以實現消息的收發。

消息

客戶端之間傳輸的數據叫做消息,或者叫記錄(Record)。 生產者對應的封裝類是ProducerRecord,消費者對應的封裝類是ConsumerRecord。

消息在服務端存儲的格式(Record Batch和Record)

Record Batch
baseOffset: int64
batchLength: int32
partitionLeaderEpoch: int32
magic: int8 (current magic value is 2)
crc: int32
attributes: int16
    bit 0~2:
        0: no compression
        1: gzip
        2: snappy
        3: lz4
        4: zstd
    bit 3: timestampType
    bit 4: isTransactional (0 means not transactional)
    bit 5: isControlBatch (0 means not a control batch)
    bit 6~15: unused
lastOffsetDelta: int32
firstTimestamp: int64
maxTimestamp: int64
producerId: int64
producerEpoch: int16
baseSequence: int32
records: [Record]
Control Batches
version: int16 (current version is 0)
type: int16 (0 indicates an abort marker, 1 indicates a commit)
Record
length: varint
attributes: int8
    bit 0~7: unused
timestampDelta: varint
offsetDelta: varint
keyLength: varint
key: byte[]
valueLen: varint
value: byte[]
Headers => [Header]
Record Header
headerKeyLength: varint
headerKey: String
headerValueLength: varint
Value: byte[]

生產者

發送消息的一方叫做生產者,接收消息的一方叫做消費者。

爲了提升發送速率,生產者不是逐條發送消息給Broker,而是批量發送的。

參數名 默認值 說明
batch.size 16384(byte) 多少條發送一次
linger.ms 5(ms) 批量發送的等待時間
acks 1 0 發出去就確認、1 leader落盤就確認 、all所有Follower同步才完成
retries 3 異常自動重試次數
buffer.memory 33554432(32M) 客戶端緩衝區大小,滿了也會觸發發送
max.block.ms 3000(ms) 獲取元數據時生產者的相親阻塞時間,超時後拋出異常

消費者

一般來說消費者有兩種消費模式,一種是pull模式,一種是push模式。

Pull模式就是消息放到Broker,消費者自己決定什麼時候去獲取。

Push模式是消息放在Consumer,只要消息到達Broker,都直接給消費者。

Kafka只有pull模式。 是因Push模式下,如果消息生產的速度遠遠大於消費者的速率,那消費者就會不堪重負,直到掛掉。而Pull模式,消費者可以自己控制一次獲取多少條消息。

參數名 默認值 說明
max.poll.records 500 一次獲取消息數
auto.commit.interval.ms 1000(ms) 消費者自動提交間隔時間
auto.offset.reset earliest 從最早的數據開始消費(earliest 、 latest、 none)

Topic

生產者如何與消費者關聯起來?其他的消息中間件的關聯名叫隊列,也就是說,生產者發送消息,要指定發給哪個隊列。消費者接收消息,要指定從哪個隊列接收。

在kafka裏面,這個隊列叫Topic,是一個邏輯概念,可以理解爲一組消息的集合。

參數名 默認值 說明
auto.create.topic.enable true 是否開啓默認創建Topic(生產環境建議關閉,手動控制)

Partition 與 Cluster

如果一個Topic中的消息太多,會帶來兩個問題:

  1. 不方便橫向擴展,比如想在集羣中把數據分佈在不同的機器上實現擴展,而不是通過升級硬件做到,如果一個Topic的消息無法在物理上拆分到多臺機器的時候,這個是做不到的。

  2. 併發或負載問題,所有客戶端操作的都是一個Topic,在高併發場景下性能會大大下降。

如何解決這個問題?我們想到的就是把一個Topic進行拆分(分片思想)。

kafka引入了一個分區(Partition)的概念。一個Topic可以劃分成多個分區。

Partition思想上有點類似於分庫分表,實現的也是橫向擴展負載的目的。

如:Topic有3個分區,生產者依次發送9條消息,對消息進行編號。

第一個分區 1、4、7,第二個分區2、5、8、第三個分區3、6、9,這個就實現了負載。

每個partition都有一個物理目錄。在配置的數據目錄下(日誌就是數據):

/tmp/kafka-logs/

test-topic-0
test-topic-1

與RabbitMQ不一樣的地方是,Partition裏面的消息被讀取後不會被刪除,所以同一批消息在一個Partition裏面順序、追加寫入的。這個也是kafka吞吐量大的一個很重要的原因。

Partition 副本 Replica機制

如果partition數據只存儲一份,在發生網絡或者硬件故障時,該分區的數據就無法訪問或者無法回覆了。

每個partition可以有若干個副本(Replica),副本必須在不同的Broker上面。一般我們說的副本包括其中的主節點。

舉例:部署了3個Broker,該Topic有3個分區,每個分區一共3個副本。

注意:這些存放相同數據的partition副本有Leader(圖中紅色)和follower(圖中綠色)的概念。Leader在哪臺機器是不一定的,是通過選舉算法選舉出來的。

生產者發消息、消費者讀消息都是針對leader,主要是爲一致性考慮,如Mysql中的主從同步會有一定的延遲問題。follower的數據是從leader同步過來的。

Segment

kafka的數據是放在後綴.log的文件裏的。如果一個partition只有一個log文件,消息不斷的追加,這個log文件也會越來越大,這個時候要檢索數據效率就很低了。

所以把partiton再做一個切分,切分出來的單位就叫做段(Segment)。kafka的存儲文件是劃分成段來存儲的。

默認存儲路徑:/tmp/kafka-logs/

每個segment都至少有1個數據文件和2個索引文件,這3個文件是成套出現的。

參數名 默認值 說明
log.segment.bytes 1G 一個segment大小

Consumer Group

如果生產者產生消息的速度過快,會造成消息在Broker的堆積,影響Broker的性能。怎麼提升消息的消費速率呢?增加消費者的數量。但是這麼多消費者,怎麼知道大家是不是消費的同一個Topic呢?

所以引入了一個Consumer Group消費組的概念,在代碼中通過group id來配置。消費同一個topic的消費者不一定是同一個組,只有group id相同的消費者纔是同一個消費者組。

注意:同一個group中的消費者,不能消費相同的partition——partition要在消費者之間分配。

Consumer Offset

上邊我們說了,partition裏面的消息是順序寫入的,被讀取之後不會被刪除。

如果消費者掛了或者下一次讀取,想要接着上次的位置讀取消息,或者從某個特定的位置讀取消息,該怎麼辦呢?會不會出現重複消費的情況?

因爲消息是有序的,我們可以對消息進行編號,用來標識一條唯一的消息。

這個編號我們不把它叫做offset,偏移量。

offset記錄着下一條將要發送給consumer的消息的序號。

這個消費者跟partition之間的偏移量沒有保存在ZK,而是直接保存在服務端。

架構圖:

總覽:

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