天天看點

Kafka簡介

Kafka是分布式流平台。

一個流平台有3個主要特征:

  • 釋出和訂閱消息流,這一點與傳統的消息隊列相似。
  • 以容災持久化方式的消息流存儲。
  • 在消息流發生時處理消息流。

Kafka通常使用在兩大類應用中:

  • 在系統或應用之間,建構實時、可靠的消息流管道。
  • 建構實時流應用程式,用于轉換或響應資料流

Kafka的幾個基本概念:

  • Kafka可以作為一個叢集運作在跨越多個資料中心的多個服務上。
  • Kafka叢集按照分類存儲的消息流叫做topic。
  • 每一個消息由一個主鍵、一個值、和一個時間戳組成。

Kafka有4個核心的API:

  • Producer API允許應用向一個或多個topic發送資訊流。
  • Consumer API允許應用訂閱一個或多個topic并處理産生的資訊流。
  • Streams API允許應用扮演一個流處理器,從一個或多個topic消費輸入流,并向一個或多個topic生産輸出流。

    實際上是轉換輸入流到輸出流。

  • Connector API建構和運作連接配接Kafka的可複用的生産者或消費者,到已存在的應用或資料系統。例如:連接配接一個關系型資料庫捕獲表中的每一次變化。

在Kafka中,用戶端和伺服器之間的通信是通過一種簡單的,高性能的,語言不可知的TCP協定完成的。

image1

Topics 和 Logs

我們了解一下Kafka為消息流提供的核心抽象——topic。

一個topic是一個消息釋出時的分類。Kafka中的topic總是有0個、1個、或多個消費者訂閱寫入其中的資料。

對于每一個topic,Kafka叢集儲存着分區日志:

image2

每一個partition是一個有序的不可改變的消息隊列, 它可以持續的追加——結構化的送出日志。partitions中的每一個記錄都會配置設定

一個有序的id,這個id叫做偏移量——每一個partition中的一個消息的唯一辨別符。

Kafka叢集通過配置保留時間持久化所有釋出的消息,不管它是否被消費。例如:設定保留時間為2天,一個消息釋出後的2天内,它可以被消費,超過2天,它将被丢棄以釋放空間。

實際上,儲存在每一個消費者基礎上的唯一進制資料是偏移量(offset)或者說是日志中消費者的位置。偏移量(offset)時候被消費者控制的:

正常情況下,一個消費者在讀取資料時,線性增加它的偏移量,但實際上,消費者控制位置,它可以按照任何順序處理和消費消息。例如:消費者可以重置一個老的偏移量,重新

處理過去的資料,也可以跳到最新的資料,從“現在時刻”起,消費資料。

這些特性意味着消費者是十分廉價的,他們可以來去自如,不會和叢集中的其他消費者沖突。例如:你可以到任何topic的消息末尾,而不影響正在消費這個topic的其他消費者。

日志中的partitions服務着幾個目的:首先,它們允許日志的大小超出适合單個伺服器的大小。每一個單獨的partition必須适合于自己的伺服器。但是一個topic可以有許多個partition

,是以它可以處理任意數量規模的資料。其次它扮演着平行的機關。

image3

分布式

日志的partitions分布在Kafka叢集中的服務上,每一個服務處理partitions中的一份。每一個partition可以通過配置服務的數量進行複制,以達到容災的目的。

每一個partition都有一個服務扮演着"leader"的角色,0個或多個服務扮演着"followers"的角色。"leader"處理partition所有的讀寫請求,"followers"通過"leader"進行資料備份。

如果"leader"失敗了,"followers"中的一個會自動變成"leader"。

異地同步

Kafka的MirrorMaker為叢集提供異地同步支援,使用MirrorMaker,消息可以跨越多個資料中心或雲區域進行複制。你可以用主-被模式進行數複制和恢複,也可以用主-主模式

把資料置于離使用者更新的地方。

生産者

生産者釋出資料到他們選擇的topic,生産者負責選擇哪一個消息配置設定到topic中的哪一個partition。它可以通過輪詢的方式簡單的實作負載均衡,或者通過消息主鍵進行語義分區。

消費者

消費者用消費組名稱标志着他們自己。釋出到topic的每一個消息都會傳送到每一個訂閱的消費組中的一個消費執行個體上。消費執行個體可以按照程序分割,也可以按照機器分割。

如果所有的消費執行個體在一個消費組下,消息實際上是在消費執行個體上進行負載均衡。

如果所有的執行個體在不同的消費組下,每一個消息都會廣播到每一個消費執行個體。

image4

兩個伺服器Kafka叢集托管四個分區(P0-P3)和兩個消費者組。消費者組A有兩個消費者執行個體,而組B有四個消費者執行個體。

通常情況下,我們發現topic都有一個小量的消費組,每一個“邏輯訂閱者”都有一個。每一個消費組都由許多消費執行個體組成,為了擴充和容災。

這僅僅在生産-訂閱語義上,訂閱者由一個消費叢集代替了單一的程序。

Kafka消費的實作方式是通過消費執行個體分割日志中的partition,是以,在任何時間點,每一個執行個體都是partition合理份額中的專一消費者。

組内保持關系的程序被Kafka協定動态的處理。如果一個新的執行個體加入了組,它會從組内的其他成員配置設定一些partition。如果一個執行個體死掉了, partitions會配置設定到剩餘的執行個體中。

Kafka僅提供partition内的消息排序,不是topic内不同partition之間的。按分區排序與按鍵分區資料的能力相結合,足以滿足大多數應用程式的需求。可是,

如果你需要消息的整體排序,它可以用一個topic隻有一個partition來完成,這意味着一個消費組中,隻有一個消費執行個體處理資料。

多租戶

你可以用多租戶方案部署Kafka叢集。多租戶可以通過配置啟用哪些topic可以生産或消費資料。還有配額操作的支援。管理者可以根據請求定義和執行配額以控制用戶端使用的代理資源。

擔保

作為進階别的Kafka,給出了一下的擔保:

  • 被發送到topic partition的消息會按照他們發送的順序追加。如果M1被相同的生産者作為M2發送,M1先發送,M1有一個較低的offset,并且在日志中先與M2出現。
  • 消費者按照日志中的順序發現消息。
  • 對于具有複制因子N的主題,我們将容忍多達N-1個伺服器故障,而不會丢失任何送出給日志的記錄。

Kafka作為消息系統

Kafka的流概念與傳統企業消息系統如何比較?

傳統的消息有連個模型:隊列和釋出-訂閱。在隊列中,每一個消息會配置設定到消費者中的一個,在釋出-訂閱模式下,每一個消息會廣播到所有的消費者。

這兩者中的每一個都有優點和缺點。隊列的優點是可以通過多個消費者執行個體分割資料的處理,這可以擴充你的處理程序。不幸的是,隊列不能有多個訂閱者,一旦一個程序

讀取了資料,它就消失了。釋出-訂閱允許你廣播資料到多個程序,消息去了每一個消費者,你沒有方式去擴充它。

Kafka消費組的概念整合了這兩個概念。作為隊列,消費組可以通過程序集合(消費組中的成員)分割處理。作為釋出-訂閱,Kafka允許你釋出消息到所有的消費組。

Kafka模型的優點是每一個topic都有這兩個屬性,它可以擴充處理和有多個訂閱者,不需要選擇其中的一種。

Kafka比傳統的消息系統有更強的排序保障。

傳統的隊列在服務端儲存消息的順序,如果多個消費者從隊列中消費資料,服務按照存儲的順序分發消息。可是,雖然服務按照順序分發資料,資料時異步的傳遞給消費者,

是以他們到達不同的消費者時是不能保證順序的。這實際上意味着消息的順序在平行消費面前是丢失的。消息系統為了解決這樣的問題,通常有一個“專用消費者”的概念,

它隻允許一個消費者從隊列消費資料,這意味着沒有平行處理。

Kafka可以更好的解決這個問題。通過有一個在topic内的平行partition的概念,Kafka既可以提供消息順序的保障,又可以通過消費處理池進行負載均衡。

這是通過将topic中的partition配置設定給消費組中的消費者來實作的,以便每一個分區被組中的一個确定的消費者消費。通過這樣做,我們確定了一個消費者

是partition的唯一讀取者,并按照順序消費資料。由于有多個partition,仍然可以通過多個消費者均衡負載。記住,組中消費者的數量不能大于partition的數量。

Kafka作為存儲系統

任何允許釋出消息并解耦消費的消息隊列實際上都扮演着一個消息的存儲系統。卡夫卡的不同之處在于它是一個非常好的存儲系統。

寫入Kafka的資料寫入磁盤并進行複制以實作容錯。Kafka允許生産者等待确認,以便寫入在完全複制之前不會被認為是完成的,并且即使寫入的伺服器失敗也能保證持續。

Kafka磁盤結構使用的規模很大 - 無論您在伺服器上有50 KB還是50 TB的持久性資料,Kafka都會執行相同的操作。作為認真考慮存儲并允許用戶端控制其讀取位置的結果,您可以将Kafka視為一種專用于高性能,低延遲送出日志存儲,複制和傳播的專用分布式檔案系統。

Kafka作為流處理

僅讀取,寫入和存儲資料流是不夠的,目标是啟用流的實時處理。

在Kafka中,流處理器是指從輸入主題擷取連續資料流,對該輸入執行一些處理并生成連續資料流以輸出主題的任何内容。

例如,零售應用程式可能會接受銷售和裝運的輸入流,并輸出一系列重新排序和對這些資料計算出的價格調整。

可以直接使用生産者API和消費者API進行簡單的處理。然而,對于更複雜的轉換,Kafka提供完全內建的Streams API。這允許建構應用程式進行非平凡的處理,進而計算聚合關閉流或将流連接配接在一起。

這個工具有助于解決這類應用程式面臨的難題:處理無序資料,重新處理代碼更改的輸入,執行有狀态的計算等。

流API基于Kafka提供的核心原語建構:它使用生産者API和消費者API輸入,使用Kafka進行有狀态存儲,并在流處理器執行個體之間使用相同的組機制來實作容錯。