Kafka及周邊深度瞭解

本文屬於原創,轉載註明出處,歡迎關注微信小程序小白AI博客 微信公衆號小白AI或者網站 https://xiaobaiai.net 或者個人CSDN http://blog.csdn.net/freeapehtml

[TOC]java

0 前言

文章有點長,可是寫的都挺直白的,慢慢看下來仍是比較容易看懂,從Kafka的大致簡介到Kafka的周邊產品比較,再到Kafka與Zookeeper的關係,進一步理解Kafka的特性,包括Kafka的分區和副本以及消費組的特色及應用場景簡介。redis

1 簡介

Apache Kafka 是一個分佈式流處理平臺,注意是平臺:sql

  • 發佈 & 訂閱,相似消息系統,併發能力強,經過集羣能夠實現數據總線做用,輕輕鬆鬆實現流式記錄數據分佈式讀寫
  • 以高容錯的方式存儲海量流式數據
  • 能夠在流式記錄數據產生時就進行處理

從上面的一個Kafka小型應用架構圖能夠了解Kafka周邊及它的實際能扮演的角色,圖中Kafka集羣鏈接了六個數據輸入輸出部分,分別是Kafka ProducerKafka Connect Source Kafka Streams/KSQLKafka ConsumerKafka Connect Sink。而這些數據的輸入輸出均可以經過Kafka提供的四個核心API組去解決(除Kafka AdminClient API外):數據庫

  • Kafka Producer API 容許一個應用程序發佈一串流式的數據到一個或者多個Kafka主題(Topic)
  • Kafka Consumer API 容許一個應用程序訂閱一個或多個主題(Topic) ,而且對接收到的流式數據進行處理
  • Kafka Streams API 容許一個應用程序做爲一個流處理器,消費一個或者多個主題(Topic)產生的輸入流,而後生產一個輸出流到一個或多個主題(Topic)中去,在輸入輸出流中進行有效的轉換
  • Kafka Connector API 容許構建並運行可重用的生產者或者消費者,將Kafka Topics鏈接到已存在的應用程序或者數據庫系統。好比,鏈接到一個關係型數據庫,捕捉表(table)的全部變動內容。

咱們對Kafka的發佈 & 訂閱功能的做用比較清楚,而圖中的KSQL和Kafka Streams是怎麼個回事呢?apache

首先咱們須要清楚什麼是流處理?流處理能夠認爲是消息的實時處理,好比在一個時間段內,源源不斷地有數據信息進來,而每時每刻都可以對這些數據有一個最後的結果處理,那麼這就是流處理,而若是是每隔一個小時或者更久處理一次,那叫大數據分析或者批處理。它的特色更可能是實時性的分析,在流式計算模型中,輸入是持續的,能夠認爲在時間上是無界的,也就意味着,永遠拿不到全量數據去作計算,同時,計算結果是持續輸出的,也即計算結果在時間上也是無界的。相似的比較有:HadoopStorm以及Spark StreamingFlink是經常使用的分佈式計算組件,其中Hadoop是對非實時數據作批量處理的組件;StormSpark StreamingFlink是針對實時數據作流式處理的組件,而Kafka Streams是後起之秀。小程序

關於KSQL呢?segmentfault

  • KSQL 是 Apache Kafka 的數據流 SQL 引擎,它使用 SQL 語句替代編寫大量代碼去實現流處理任務,而Kafka Streams是Kafka中專門處理流數據的
  • KSQL 基於 Kafka 的 Stream API 構建,它支持過濾(filter)、轉換(map)、聚合(aggregations)、鏈接(join)、加窗操做和 Sessionization(即捕獲單一會話期間的全部的流事件)等流處理操做,簡化了直接使用Stream API編寫 Java 或者 Scala 代碼,只需使用簡單的 SQL 語句就能夠開始處理流處理
  • KSQL 語句操做實現上都是分佈式的、容錯的、彈性的、可擴展的和實時的
  • KSQL 的用例涉及實現實時報表和儀表盤、基礎設施和物聯網設備監控、異常檢測和欺騙行爲報警等

2 相關概念簡介

  • Broker:Kafka集羣包含一個或多個服務器,這種服務器被稱爲broker
  • Topic:每條發佈到Kafka集羣的消息都有一個類別,這個類別被稱爲Topic
  • Partition:Parition是物理上的概念,每一個Topic包含一個或多個Partition
  • Replication:副本,一個partition能夠設置一個或者多個副本,副本主要保證系統可以持續不丟失地對外提供服務。在建立topic的時候能夠設置partition的replication數
  • Segment:段文件,kafka中最小數據存儲單位,kafka能夠存儲多個topic,各個topic之間隔離沒有影響,一個topic包含一個或者多個partition,每一個partition在物理結構上是一個文件夾,文件夾名稱以topic名稱加partition索引的方式命名,一個partition包含多個segment,每一個segment以message在partition中的起始偏移量命名以log結尾的文件,producer向topic中發佈消息會被順序寫入對應的segment文件中。kafka爲了提升寫入和查詢速度,在partition文件夾下每個segment log文件都有一個同名的索引文件,索引文件以index結尾。
  • Offset:消息在分區中偏移量,用來在分區中惟一地標識這個消息。
  • Producer:消息生產者,負責發佈消息到Kafka broker
  • Consumer:消息消費者,向Kafka broker讀取消息的客戶端
  • Consumer Group:每一個Consumer屬於一個特定的Consumer Group(可爲每一個Consumer指定group name,若不指定group name則屬於默認的group)

3 Kafka與ActiveMQ、ZeroMQ、RabbitMQ、RocketMQ、Redis

這個主要是針對消息中間件的選型評估,這裏咱們講述一些概念。其餘更詳細的這裏有篇文章講了: https://juejin.im/post/5b3204...微信小程序

3.1 消息隊列、點對點和PUB/SUB

在開始以前,咱們也須要稍微瞭解下JMS(Java Messaging System),是一個Java平臺中關於面向消息中間件(MOM)的API。JMS支持兩種消息模式,一個就是P2P模式,一個就是發佈訂閱模式。後面會說到哪些消息件支持JMS。api

消息隊列有兩種消息模型:點對點(Point to Point,PTP)和發佈/訂閱(PUB/SUB)模式。

消息隊列點對點,顧名思義,是一個隊列,信息只能一對一,一個消息被一個消費者使用完了,那麼就不會存在隊列中了,就像郵差給別人投遞郵件,不可能這封信還有副本,並且還能保證這封信安全送到指定的人手裏(這是框架賦予的能力)。

PUB/SUB消息訂閱發佈就不同了,它的特徵就是支持多對一,一對一,一對多,就像期刊報社同樣,出版的期刊或者報紙,須要能夠傳遞到不一樣人手裏,並且還能夠拿到之前日期的期刊或者報紙(這是框架賦予的能力)。

  • RabbitMQ是消息代理,持多種消息傳遞協議,如AMQP,MQTT3.1,XMPP, SMTP, STOMP,HTTP, WebSockets協議,由內在高併發的Erlanng語言開發,用在實時的對可靠性要求比較高的消息傳遞上。它既支持消息隊列點對點,也支持PUB/SUB。RabbitMQ對JMS全部特性並不徹底支持(https://www.rabbitmq.com/jms-...
  • Redis之內存數據庫而聞名。可是,也能夠將其用做消息隊列點對點和PUB/SUB管理工具,不過由於內存緩衝區的效率,若是消費者失去了與隊列的鏈接,那麼頗有可能在鏈接丟失時丟失消息。另外,在實現消息隊列點對點功能上,至少要建立3個隊列:主隊列、工做隊列、被拒絕隊列,實現有點複雜。
  • Apache RocketMQ做爲阿里開源的一款高性能、高吞吐量的分佈式消息中間件,PUB/SUB就是基本功能了,支持消息優先級、消息有序保證、消息過濾,保證每一個消息至少投遞一次。RocketMQ的集羣消費功能大等於PTP模型。由於RocketMQ單個Consumer Group內的消費者相似於PTP,單個Consumer Group裏面的消費者均攤消息,等於實現點對點功能,接收者單位是Group。
  • Apache ActiveMQ支持點對點和PUB/SUB,支持多種跨語言客戶端和協議,具備易於使用的企業集成模式和許多高級功能,同時徹底支持JMS 1.1和j2ee1.4
  • ZeroMQ是用C實現的,性能高、輕量級天然是它的特色。ZeroMQ 並不是嚴格意義上的 at least once 或者 at most once,以其 Pub/Sub 模式來講,ZeroMQ 構建了消息確認和重傳機制,卻未對消息進行持久化,那麼內存耗盡或者進程崩潰都會形成消息丟失,而重傳則可能會形成消息被髮送 1 到 n 次。固然,在企業級WEB服務中,尤爲是微服務中咱們對ZeroMQ的選擇是偏少的。
  • Kafka更多的是做爲發佈/訂閱系統,結合Kafka Stream,也是一個流處理系統

3.2 關於持久化

  • ZeroMQ支持內存、磁盤,不支持數據庫持久化
  • Kafka支持內存、磁盤(主),支持數據庫持久化,支持大量數據堆積
  • RabbitMQ支持內存、磁盤,支持數據堆積,可是數據堆積影響生產效率
  • ActiveMQ支持內存、磁盤,自持數據庫持久化
  • RocketMQ的全部消息都是持久化的,先寫入系統 pagecache(頁高速緩衝存儲器),而後刷盤,能夠保證內存與磁盤都有一份數據,訪問時,直接從內存讀取

3.3 關於吞吐量

  • RabbitMQ在吞吐量方面稍遜於Kafka,他們的出發點不同,RabbitMQ支持對消息的可靠的傳遞,支持事務,不支持批量的操做;基於存儲的可靠性的要求存儲能夠採用內存或者硬盤。
  • Kafka具備高的吞吐量,內部採用消息的批量處理,zero-copy機制,數據的存儲和獲取是本地磁盤順序批量操做,具備O(1)的複雜度,消息處理的效率很高
  • ZeroMQ也具備很高的吞吐量
  • RocketMQ相比RabbitMQ的吞吐量要大,可是沒有Kafka的大
  • ActiveMQ相對RabbitMQ而言要弱

3.4 關於集羣

  • Kafka:自然的'Leader-Slave'無狀態集羣,每臺服務器既是Master也是Slave
  • ZeroMQ:去中心化,不支持集羣
  • RabbitMQ:支持簡單集羣
  • RocketMQ:支持集羣,經常使用多對'Master-Slave' 模式
  • ActiveMQ:支持簡單集羣模式,好比'主-備',對高級集羣模式支持很差。

3.5 關於負載均衡

  • Kafka:支持負載均衡,結合內置Zookeeper,有效的實現Kafka集羣的Load Balancer
  • ZeroMQ:去中心化,不支持負載均衡,自己只是一個多線程網絡庫
  • RocketMQ:支持負載均衡
  • RabbitMQ:對負載均衡的支持很差
  • ActiveMQ:支持負載均衡,能夠基於Zookeeper實現負載均衡

3.6 關於單機隊列數

單機隊列數越大,單機能夠建立更多主題,由於每一個主題都是由一批隊列組成,消費者的集羣規模和隊列數成正比,隊列越多,消費類集羣能夠越大。

  • Kafka單機超過64個隊列/分區,Load會發生明顯的飆高現象,隊列越多,load越高,發送消息響應時間變長。Kafka分區數沒法過多的問題
  • RocketMQ單機支持最高5萬個隊列,負載不會發生明顯變化

4 Kafka Streams與Storm、Spark Streaming、Flink

4.1 流處理框架特色和處理方式

上面咱們說過了流處理就是對數據集進行接二連三的處理,聚合,分析的過程,它的延遲要求儘量的低(毫秒級或秒級),從流處理的幾個重要方面來說述,分佈式流處理框架須要具備以下特色:

  • 消息傳輸正確性保證,保證區分有:

    • 消息At Most Once,即消息能夠丟失或者傳遞一次
    • 消息At Least Once,即消息至少一次,存在重複傳遞的狀況
    • 消息Exactly Once,即消息不會丟失也不會重複傳遞
  • 高容錯性:在發生諸如節點故障、網絡故障等故障時,框架應該可以恢復,而且應該從它離開的地方從新開始處理。這是經過不時地檢查流到某個持久性存儲的狀態來實現的。
  • 狀態管理:絕大部分分佈式系統都須要保持狀態處理的邏輯。流處理平臺應該提供存儲,訪問和更新狀態信息的能力
  • 高性能:這包括低延遲(記錄處理的時間)、高吞吐量(throughput,記錄處理/秒)和可伸縮性。延遲應儘量短,吞吐量應儘量多,不過這很難同時兼顧到這二者,須要作一個平衡
  • 高級特性Event Time Processing(事件時間處理)、水印、支持窗口,若是流處理需求很複雜,則須要這些特性。例如,基於在源代碼處生成記錄的時間來處理記錄(事件時間處理)
  • 成熟度:若是框架已經被大公司證實並在大規模上進行了測試,這就很好。更有可能在論壇或者其餘地方得到良好的社區支持和幫助

流處理的方式有兩種:

  • Native Streaming

    • 每個傳入的記錄一到達就被處理,而沒必要等待其餘記錄。有一些持續運行的進程(咱們稱之爲operators/tasks/bolts,命名取決於框架)會永遠運行,而且每一個記錄都會通過這些進程來進行處理,示例:Storm、Flink、Kafka Streams。
  • Micro-batching

    • 快速批處理,這意味着每隔幾秒鐘傳入的記錄都會被批處理在一塊兒,而後以幾秒的延遲在一個小批中處理,例如: Spark Streaming

這兩種方法都有一些優勢和缺點。當每一個記錄一到達就被處理時,處理結果就感受很天然,容許框架實現儘量最小的延遲。但這也意味着在不影響吞吐量的狀況下很難實現容錯,由於對於每一個記錄,咱們須要在處理後跟蹤和檢查點。此外,狀態管理也很容易,由於有長時間運行的進程能夠輕鬆地維護所需的狀態;而小批處理方式,則徹底相反,容錯是附帶就有了,由於它本質上是一個批處理,吞吐量也很高,由於處理和檢查點將一次性完成記錄組。但它會以必定的延遲爲代價,讓人感受不像是天然的流處理。同時,高效的狀態管理也將是一個挑戰。

4.2 主流流處理框架比對

流處理框架 特色 缺點
Strom是流處理界的hadoop。它是最古老的開源流處理框架,也是最成熟、最可靠的流處理框架之一 很是低的延遲,真正的流處理,成熟和高吞吐量;很是適合不是很複雜流式處理場景; 消息至少一次保證機制;沒有高級功能,如事件時間處理、聚合、窗口、會話、水印;
Spark Streaming 支持Lambda架構,免費提供Spark;高吞吐量,適用於許多不須要子延遲的場景;簡單易用的高級api;社區支持好;此外,結構化流媒體更爲抽象,在2.3.0版本中能夠選擇在微批處理和連續流媒體模式之間切換;保證消息剛好傳遞一次; 不是真正的流媒體,不適合低延遲要求;參數太多,很難調參;在許多高級功能上落後於Flink;
Flink 支持Lambda架構;開源流媒體領域的創新領導者;第一個真正的流式處理框架,具備全部高級功能,如事件時間處理、水印等;低延遲,高吞吐量,可根據須要配置;自動調整,沒有太多參數須要調整;保證消息剛好傳遞一次;在像Uber、阿里巴巴這樣的規模大公司接受。 進入流處理界晚,還沒被普遍接受;社區支持相對較少,不過在蓬勃發展;
Kafka Streams 很是輕量級的庫,適用於微服務和物聯網應用;不須要專用羣集;繼承了卡夫卡全部的優良品質;支持流鏈接,內部使用rocksDb來維護狀態。保證消息剛好傳遞一次; 與卡夫卡緊密結合,不然沒法使用;剛剛起步,還未有大公司選擇使用;不合適重量級的流處理;

總的來講,Flink做爲專門流處理是一個很好的選擇,可是對於輕量級而且和Kafka一塊兒使用時,Kafka Streaming是個不錯的選擇。

5 Zookeeper & Kafka?

Zookeeper在Kafka集羣中主要用於協調管理,主要做用:

  • Kafka將元數據信息保存在Zookeeper中
  • 經過Zookeeper的協調管理來實現整個kafka集羣的動態擴展
  • 實現整個集羣的負載均衡
  • Producer經過 Zookeeper 感知 partition 的Leader
  • 保存Consumer消費的狀態信息。
  • 經過 ZK 管理集羣配置,選舉 Kafka Leader,以及在 Consumer Group 發生變化時進行 Rebalance
Zookeeper是由java編寫的,因此須要先安裝JDK。

5.1 Zookeeper是必需要有的嗎?

是的,在Kafka中,儘管你只想使用一個代理、一個主題和一個分區,其中有一個生產者和多個消費者,不但願使用Zookeeper,浪費開銷,可是這狀況也須要Zookeeper,協調分佈式系統中的任務、狀態管理、配置等,並且使用單節點的場景顯然沒有利用到Kafka的優勢。

另外,Apacke Kafka維護團隊開始討論去除Zookeeper了(2019年11月6日),目前,Kafka使用ZooKeeper來存儲分區和代理的元數據,並選擇一個Broker做爲Kafka控制器,而但願經過刪除對ZooKeeper的依賴,將使Kafka可以以一種更具伸縮性和健壯性的方式管理元數據,啓用對更多分區的支持,它還將簡化Kafka的部署和配置,由於ZooKeeper是一個單獨的系統,具備本身的配置文件語法,管理工具和部署模式。另外Kafka和ZooKeeper配置是分開的,因此很容易出錯。例如,管理員可能在Kafka上設置了SASL,而且錯誤地認爲他們已經保護了經過網絡傳輸的全部數據。實際上,這樣作還必須在單獨的外部ZooKeeper系統中配置安全性。統一兩個系統將提供統一的安全配置模型。未來Kafka可能但願支持單節點Kafka模式,這對於想要快速測試Kafka而無需啓動多個守護程序的人頗有用,刪除掉ZooKeeper的依賴關係使之成爲可能。

5.2 Zookeeper在Kafka中是自帶的,可使用自定義安裝的ZK嗎?

這個固然是能夠的,你能夠不啓動Kafka自帶的ZK。

6 理解Kafka數據模型: Topics、Partitions及Replication

Kafka的分區機制實現了Topic的水平擴展和順序性保證。這一節咱們深度瞭解下是怎麼回事?

Topic在邏輯上能夠被認爲是一個隊列。每條消費都必須指定它的topic,能夠簡單理解爲必須指明把這條消息放進哪一個隊列裏。爲了使得Kafka的吞吐率能夠水平擴展,物理上把topic分紅一個或多個partition,每一個partition在物理上對應一個文件夾,該文件夾下存儲這個partition的全部消息和索引文件,好比咱們建立了一個主題叫xiaobiao,而後Kafka有三個Brokers,結合《Kafka,ZK集羣開發或部署環境搭建及實驗》這一篇文章中的實驗環節,咱們建立主題的時候須要指定:

# 利用Kafka提供的命令行腳本,建立兩分區兩副本的主題xiaobiao
./bin/kafka-topics.sh --create --zookeeper localhost:2181,localhost:2182,localhost:2183 --replication-factor 2 --partitions 2 --topic xiaobiao

兩分區,兩副本,如何理解呢?咱們指定了三個服務,咱們將xiaobiao主題分爲兩個子部分,能夠認爲是兩個子隊列,對應的在物理上,咱們能夠在log.dir參數設定的目錄下看到兩個文件夾xiaobiao-0xiaobiao-1,不過根據Kafka的分區策略,對於多個Kafka Brokers,分區(多個文件夾)通常會分散在不一樣的Broker上的log.dir設定的目錄下,當只有一個Broker時,全部的分區就只分配到該Broker上,消息會經過負載均衡發佈到不一樣的分區上,消費者會監測偏移量來獲取哪一個分區有新數據,從而從該分區上拉取消息數據。這是分區的表現。不過度區數越多,在必定程度上會提高消息處理的吞吐量,由於Kafka是基於文件進行讀寫,所以也須要打開更多的文件句柄,也會增長必定的性能開銷,可是Kafka社區已經在制定解決方案,實現更多的分區,而性能不會受太多影響。

若是分區過多,那麼日誌分段也會不少,寫的時候因爲是批量寫,其實就會變成隨機寫了,隨機 I/O 這個時候對性能影響很大。因此通常來講 Kafka 不能有太多的 Partition。

那副本呢?顧名思義,即主題的副本個數,即咱們上面有兩個主題分區,即物理上兩個文件夾,那麼指定副本爲2後,則會複製一份,則會有兩個xiaobai-0兩個xiaobai-1,副本位於集羣中不一樣的broker上,也就是說副本的數量不能超過broker的數量,不然建立主題時就會失敗。那麼副本有什麼用呢?當Kafka某個代理(Broker)出現故障且沒法爲請求(Consumer)提供服務時,爲了達到可用性的惟一目的而設置有多個數據副本,這樣就不擔憂集羣中某個Broker掛掉了,這裏也進一步能夠知道,達到這個做用,那麼一個主題的分區副本是須要在不一樣的Broker上的,並且對應副本分區是保持數據同步的。不可避免地,副本越多,那麼對Kafka的吞吐量是會形成影響的。下圖就是Replication Factor等於2時數據同步示意圖:

分區Leader: 對於每一個分區,都有一個副本被指定爲Leader。Leader負責發送和接收該分區的數據,全部其餘副本都稱爲分區的同步副本(或跟隨者)。

In sync replicas是分區的全部副本的子集,該分區與主分區具備相同的消息。

好比當Broker2 掛掉後,因爲broker 2是分區1的負責人(Leader),所以如今沒法訪問分區1。發生這個狀況的時候Kafka會自動選擇一個同步副本(在上圖中只有一個副本)並使它成爲領導者(Leader)。如今,當broker 2從新上線時,broker 2中分區1能夠再次嘗試成爲Leader。

固然,上面所說副本和分區沒有具體深刻到內部機制是怎麼實現的,怎麼保證的,這裏就先不展開了。

7 Kafka的Consumer Group

Consumer Group:每個消費者實例都屬於一個消費Group,每一條消息只會被同一個消費Group裏的一個消費者實例消費(不一樣消費Group能夠同時消費同一條消息)。不一樣於通常的隊列,Kafka實現了消息被消費完後也不會將消息刪除的功能,即咱們可以藉助Kafka實現離線處理和實時處理,跟Hadoop和Flink這二者特性能夠對應起來,所以能夠分配兩個不一樣消費組分別將數據送入不一樣處理任務中。

8 總結

這一篇文章讓咱們對Kafka有了個基本的認識,能夠作消息訂閱/發佈系統,能夠作實時流處理,對Kafka的分區和副本有了必定的認識,對Kafka的消費組的特性也有了個基本瞭解,接下來就進入實踐,實踐事後,咱們再深刻探討Kafka的內部原理和實現機制。

9 參考資料

本文屬於原創,轉載註明出處,歡迎關注CSDNfreeape或微信小程序小白AI博客 微信公衆號小白AI或者網站 https://xiaobaiai.net

相關文章
相關標籤/搜索