kafka簡介

簡介

Apache kafka 是一個分布式的基于push-subscribe的消息系統,它具備快速、可擴展、可持久化的特點。它現在是Apache旗下的一個開源系統,作為hadoop生態系統的一部分,被各種商業公司廣泛應用。它的最大的特性就是可以實時的處理大量數據以滿足各種需求場景:比如基于hadoop的批處理系統、低延遲的實時系統、storm/spark流式處理引擎。

kafka簡介

特性

  • 高吞吐量、低延遲:kafka每秒可以處理幾十萬條消息,它的延遲最低只有幾毫秒

  • 可擴展性:kafka集群支持熱擴展

  • 持久性、可靠性:消息被持久化到本地磁盤,并且支持數據備份防止數據丟失

  • 容錯性:允許集群中節點失?。ㄈ舾北緮盗繛閚,則允許n-1個節點失?。?/p>

  • 高并發:支持數千個客戶端同時讀寫


架構組件

Kafka中發布訂閱的對象是topic。我們可以為每類數據創建一個topic,把向topic發布消息的客戶端稱作producer,從topic訂閱消息的客戶端稱作consumer。Producers和consumers可以同時從多個topic讀寫數據。一個kafka集群由一個或多個broker服務器組成,它負責持久化和備份具體的kafka消息。

  • Topic:消息存放的主題

  • Producer:生產者,負責push消息到指定的Broker的Topic中

  • Consumer:消費者

  • Broker:Kafka的服務實例,主要負責創建Topic,存儲Producer所發布的消息,記錄消息處理過程,先將消息保存到內存中,再落地到磁盤

  • Replication-factor:復制因子(kafka容錯機制),即副本數量,一般與Broker數量保持一致

  • Partitions:分區(每個分區只能被同一個消費者組內的一個消費者消費)

  • Leaders:選舉partition中的副本為leader,負責處理讀寫

  • Follower: 未被選舉為leader的副本為follower,負責備份數據

  • Zookeeper:注冊消息,用于保存broker節點信息,維護ISR和OSR隊列,partition的offset等(ZK在kafka2.8版本之后移除,offset保存在本地)


副本同步機制

kafka 0.8以后,提供了HA機制,就是replica副本機制。每個partition的數據都會同步到其他機器上,形成自己的多個replica副本。然后所有replica會選舉一個leader出來,那么生產和消費都跟這個leader打交道,然后其他replica就是follower。寫的時候,leader會負責把數據同步到所有follower上去,讀的時候就直接讀leader上數據即可。

[圖片上傳失敗...(image-6f7b38-1743417387765)]

Kafka 生產者ack機制

  • ack=0:

    • 意義:生產者在成功將消息發送給服務端之后不等待任何確認

    • 結果:生產者不知道消息是否成功到達服務端,容易造成消息丟失

  • ack=1:

    • 意義:生產者在成功將消息發送給服務端之后,等待leader的確認

    • 結果:意味著leader節點成功接收數據,但是不一定同步了其他副本

  • ack=all 或 ack=-1:

    • 意義:生產者在成功將消息發送給服務端之后,等待所有partition的副本確認

    • 結果:當所有副本都接收到數據之后,才認為消息被成功提交

Kafka 如果設置了ack(ack!=0),需要設置超時時間(retry.backoff.ms)和重試次數(retries)


ack過程中出現網絡問題,導致生產者重復發送消息怎么處理?

重復產生的核心原因
  • 超時與重試機制 當 Producer 發送消息后,若在 request.timeout.ms(默認 30 秒)內未收到 Broker 的 ack 確認,Producer 會認為消息發送失敗并觸發重試(retries 參數控制重試次數)。 風險場景

    • Broker 實際已成功寫入消息,但 ack 響應因網絡延遲未及時到達 Producer。

    • Producer 重試時,Broker 會再次寫入相同的消息(若未啟用冪等性),導致消息重復。

  • Broker 的寫入機制 Kafka 的 Partition 日志是僅追加(append-only)的,即使消息內容相同,重試時也會被當作新消息寫入(除非開啟冪等性)。

避免重復的解決方案

(1) 啟用 Producer 冪等性

  • 配置方式: 在 Producer 中設置 enable.idempotence=true(需同時滿足 acks=allretries > 0)。

  • 原理

    • Producer 為每個消息分配唯一 PID(Producer ID)序列號。

    • Broker 根據 PID + 分區號 + 序列號 去重,拒絕重復消息。

  • 適用場景: 單 Producer 實例內保證 Exactly-Once 語義,避免因重試導致的重復。

(2) 使用 Kafka 事務

  • 配置方式

    • 設置 transactional.id 并調用 initTransactions()beginTransaction()、commitTransaction()。
  • 原理

    • 事務機制結合冪等性,確??缍鄠€ Partition 和 Consumer 的原子性操作。

    • Broker 會記錄事務狀態,中斷的事務自動回滾。

  • 適用場景: 需要跨多個消息或“讀-處理-寫”鏈路的 Exactly-Once 語義(如 Kafka Streams)。

(3) 業務端去重

  • 實現方式

    • 在消息中攜帶唯一標識(如 UUID 或業務主鍵)。

    • 消費者端根據唯一標識去重(如寫入數據庫時檢查主鍵沖突)。

  • 適用場景: 無法啟用冪等性或事務的舊版本 Kafka,或需要兼容其他消息系統的場景。


ISR 機制

Kafka 服務端根據副本同步的情況,分成了三個集合:

AR(Assigned Replicas):包括ISR和OSR

ISR(In-sync Replicas):和leader保持同步的副本集合,可以認為是可靠數據(leader故障之后會在這個集合重新選舉)

OSR(Out-sync Replicas):和leader副本同步失效的副本集合(副本還會繼續同步數據,同步成功之后會進入ISR)


Kafka 數據持久化機制

Kafka 默認使用操作系統的頁緩存(page cache)機制,將消息寫入內存中的頁緩存,而非立即刷盤(高吞吐的原因)

默認情況下,Kafka 通過以下兩個參數控制主動刷盤:

  • log.flush.interval.messages:累計多少條消息后觸發刷盤(默認 Long.MAX_VALUE,即不主動觸發)

  • log.flush.interval.ms:間隔多少毫秒后觸發刷盤(默認 null,即不主動觸發) 實際默認行為:依賴操作系統后臺線程(如 Linux 的 pdflush)自動刷盤,通常延遲約 30 秒

Broker 端配置

  • 強制刷盤 修改 log.flush.interval.messageslog.flush.interval.ms,例如:

    • log.flush.interval.messages=1 # 每條消息都刷盤(極端情況,性能極低)

    • log.flush.interval.ms=1000 # 每秒刷盤一次

此配置會顯著降低吞吐量,僅適用于對數據丟失零容忍的場景。


Kafka 數據模型與消息存儲機制

[圖片上傳失敗...(image-4d351-1743417387765)]

在同一個Topic下,一個partition對應一個唯一的文件夾,在文件夾下,kafka 消息是采用 Segment File的存儲方式進行存儲

Segment File:Segment由.index文件和.log文件組成,將大文件拆分成小文件來存儲(加快IO加載

.index文件:索引文件,以key-value格式存儲,key-表示索引文件的第幾條消息;value-表示這條消息在log file中的物理偏移量

.log文件:數據存儲文件

如何通過 offset 找到 某一條消息呢?

  1. 首先會根據 offset 值去查找 Segment 中的 index 文件,因為 index 文件是以上個文件的最大 offset 偏移命名的所以可以通過二分法快速定位到索引文件。

  2. 找到索引文件后,索引文件中保存的是 offset 和對應的消息行在 log 日志中的存儲行號,因為 Kafka 采用稀疏矩陣的方式來存儲索引信息,并不是每一條索引都存儲,所以這里只是查到文件中符合當前 offset 范圍的索引。

  3. 拿到 當前查到的范圍索引對應的行號之后再去對應的 log 文件中從 當前 Position 位置開始查找 offset 對應的消息,直到找到該 offset 為止。

每一條消息的組成內容有如下字段:

Copy
offset: 4964(邏輯偏移量) 
position: 75088(物理偏移量) 
CreateTime: 1545203239308(創建時間) 
isvalid: true(是否有效)
keysize: -1(鍵大小) 
valuesize: 9(值大小) 
magic: 2 
compresscodec: NONE(壓縮編碼) 
producerId: -1
producerEpoch: -1(epoch號) 
sequence: -1(序號) 
isTransactional: false(是否事務) 
headerKeys: []
payload: message_0(消息的具體內容)

Kafka pull & push

pull是指consumer來拉取消息(默認);push是指kafka主動推送消息給consumer

pull模式:根據consumer的消費能力進行數據拉取,可以批量拉或者單條拉;可以設置不同的提交方式實現不同的傳輸語義

缺點:如果kafka沒有數據會導致consumer空循環(可以通過設置拉取數據為空或沒達到一定數量阻塞來解決)

push模式:不會導致consumer循環等待

缺點:速率固定、忽略consumer的消費能力,可能導致拒絕服務或網絡擁堵等情況


kafka常見問題

1、消息冪等性(重復消費)

重復消費只針對消費者端而言,消費者要保證消息的冪等性,一般要結合業務場景進行,主要有兩種解決方案:

1)redis:消費數據后把消息的唯一鍵存到redis中,每次消費的時候去redis查一下key是否存在

2)mysql:消費數據后把消息的唯一鍵存到mysql中,每次消費的時候查mysql

2、數據丟失

  • 消費者:消費者自動提交offset的時候會有數據丟失的情況,改為手動提交offset可解決,極端情況下數據處理完后提交offset的時候掛了,可通過加冪等性操作解決

  • kafka:kafka某個broker宕機,重新選舉leader時有數據未同步時會有消息丟失的情況,可通過設置參數(保證數據寫入到每個副本后才算寫入成功)解決

  • 生產者:設置acks=all即可避免丟失數據

3、順序性

  • 生產者:生產者沒有順序性問題

  • kafka:partition內部有序,多個partition時無法保證順序,對需要順序消費的數據指定到同一個partition即可保證順序

  • 消費者:同一個partition時,當消費者內部啟用多線程時會導致順序錯亂,可在消費者內部啟用內存隊列來保證多線程的順序

4、kafka 高性能高吞吐原因

  • 磁盤順序讀寫:

    • Kafka 將消息按順序追加(Append)到 Partition 日志文件末尾,避免機械硬盤磁頭頻繁尋道

    • 消費者按偏移量(Offset)順序讀取消息,充分利用操作系統的磁盤預讀

    • 頁緩存(page cache):消息直接寫入內存頁緩存,由操作系統異步刷盤,讀操作優先訪問緩存,減少物理磁盤 I/O

  • 零拷貝

    • 傳統數據拷貝流程: 磁盤文件 → 內核緩沖區 → 用戶空間緩沖區 → Socket 緩沖區 → 網卡 4 次上下文切換 + 2 次 CPU 拷貝

    • Kafka 優化(sendfile系統調用): 磁盤文件 → 內核緩沖區 → 網卡 2 次上下文切換 + 0 次 CPU 拷貝,減少 50% 以上 CPU 消耗

  • 分區分段+索引:分區是指partition,分段是指segment文件,索引是指segment里的.index索引

    • 分區(Partition)機制

      • 數據分片:每個 Topic 劃分為多個 Partition,分布在不同 Broker 上。

      • 并行讀寫:生產者和消費者可同時向多個 Partition 寫入/讀取數據,充分利用集群資源。

      • 擴展性:通過增加 Partition 和 Broker,線性提升吞吐量。

    • 生產者負載均衡

      • 分區策略

        • 默認輪詢(Round Robin)或按 Key 哈希,確保數據均勻分布。

        • 自定義策略支持業務特化路由。

    • 消費者組(Consumer Group)

      • 并行消費:同一消費者組內多個消費者實例分別消費不同 Partition,提升消費速度。

      • 水平擴容:增加消費者數量即可擴展消費能力(需 Partition 數量 ≥ 消費者數量)。

  • 批量處理(Batching)

    • 生產者端

      • 消息積累到 batch.size(默認 16KB)或 linger.ms(默認 0ms)后批量發送,減少網絡請求次數。

      • 壓縮(Compression):支持 GZIP、Snappy、LZ4、Zstandard,降低網絡傳輸量(尤其文本類消息)。

    • Broker 端

      • 批量寫入磁盤,減少磁盤尋址次數。
    • 消費者端

      • 批量拉取消息(max.poll.records 控制單次拉取數量)。
  • 直接操作頁緩存(page cache):消息直接寫入內存頁緩存,由操作系統異步刷盤,讀操作優先訪問緩存,減少物理磁盤 I/O

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 一、簡介 Kafka 是一個分布式的基于發布/訂閱模式的消息隊列(Message Queue),主要應用于 大數...
    brayden_yang閱讀 297評論 0 1
  • 1,消息引擎系統 1)Kafka是消息引擎系統。兩個重要因素: 消息設計、傳輸協議設計。2)Kafka消息是結構化...
    沐兮_d64c閱讀 1,908評論 0 13
  • Kafka的主要特點:1. 為發布和訂閱提供高吞吐量,每秒可產生25萬消息(50MB),每秒可處理55萬消息(11...
    zi萱閱讀 665評論 0 2
  • 1.kafka 集群的架構 Kafka是最初由Linkedin公司開發,是一個分布式、支持分區的(partitio...
    本能帥閱讀 269評論 0 1
  • 夜鶯2517閱讀 127,752評論 1 9