1.1、簡(jiǎn)介
ApacheKafka?是一個(gè)分布式流媒體平臺(tái)。 這到底是什么意思呢?
- 它可以讓你發(fā)布和訂閱消息流。 在這方面,它類似于消息隊(duì)列或企業(yè)消息傳遞系統(tǒng)。
- 它允許您以容錯(cuò)方式存儲(chǔ)消息流。
- 它可以讓你處理產(chǎn)生的流式消息。
Kafka的優(yōu)勢(shì)在哪里?
- 在系統(tǒng)或應(yīng)用程序之間構(gòu)建可靠的實(shí)時(shí)數(shù)據(jù)流管道
- 構(gòu)建實(shí)時(shí)流應(yīng)用程序,可以轉(zhuǎn)換或響應(yīng)數(shù)據(jù)流
要理解kafka必須要了解一下概念:
- Kafka在一個(gè)或多個(gè)服務(wù)器上的集群運(yùn)行。
- Kafka集群以叫做主題(topic)的類別存儲(chǔ)記錄流。
- 每個(gè)記錄(消息)由一個(gè)鍵,一個(gè)值和一個(gè)時(shí)間戳組成。
Kafka有四個(gè)核心API:
- Producer API允許應(yīng)用程序?qū)⒁唤M記錄發(fā)布到一個(gè)或多個(gè)Kafka主題。
- Consumer API允許應(yīng)用程序訂閱一個(gè)或多個(gè)主題并處理產(chǎn)生給他們的消息流。
- Streams API允許應(yīng)用程序充當(dāng)流處理器,從一個(gè)或多個(gè)主題中消費(fèi)輸入流,并將輸出流生成為一個(gè)或多個(gè)輸出主題,從而將輸入流有效地轉(zhuǎn)換為輸出流。
- Connector API允許構(gòu)建和運(yùn)行可重復(fù)使用的生產(chǎn)者或消費(fèi)者,將Kafka主題連接到現(xiàn)有的應(yīng)用程序或數(shù)據(jù)系統(tǒng)。 例如,連接到關(guān)系數(shù)據(jù)庫(kù)的連接器可能會(huì)捕獲對(duì)表的每個(gè)更改。

在Kafka中,客戶端和服務(wù)器之間的通信是通過(guò)一個(gè)簡(jiǎn)單的,高性能的,與編程語(yǔ)言無(wú)關(guān)的TCP協(xié)議完成的。 這個(gè)協(xié)議是版本化的,并保持與舊版本的向后兼容性。 我們?yōu)镵afka提供了一個(gè)Java客戶端,但客戶端可以使用多種語(yǔ)言。
主題和日志
讓我們先深入kafka為消息流提供的一個(gè)核心抽象- 主題(topic)。
Topic是消息發(fā)布到哪一個(gè)類別或者提要的名稱。Kafka的主題可以是多訂閱模式的,也就是說(shuō)一個(gè)主題可以有0個(gè)、1個(gè)或者多個(gè)消費(fèi)者去消費(fèi)寫入該主題的數(shù)據(jù)。
對(duì)于每個(gè)主題,Kafka集群維護(hù)一個(gè)分區(qū)日志,如下所示:

每個(gè)分區(qū)是一個(gè)有序的,不可變的消息序列,不斷追加到結(jié)構(gòu)化的提交日志(文件)中。 分區(qū)中的每個(gè)消息分配一個(gè)連續(xù)的id號(hào),稱為偏移量(offset),用于唯一標(biāo)識(shí)分區(qū)內(nèi)的每條消息。
Kafka集群使用可配置的保留期限來(lái)保留所有已發(fā)布的消息(無(wú)論是否已被使用)。 例如,如果保留策略設(shè)置為兩天,則在消息發(fā)布后的兩天內(nèi),消息可以可供使用,之后將被丟棄以騰出空間。Kafka性能對(duì)數(shù)據(jù)大小不敏感,所以長(zhǎng)時(shí)間存儲(chǔ)數(shù)據(jù)不成問(wèn)題。

實(shí)際上,以消費(fèi)者為單位保留的唯一元數(shù)據(jù)是消費(fèi)者在日志中的偏移或位置。這個(gè)偏移量是由消費(fèi)者控制的:消費(fèi)者通常會(huì)在讀取記錄時(shí)線性地推進(jìn)其偏移量,但事實(shí)上,由于消費(fèi)者的位置是由消費(fèi)者控制的,所以它可以以任何喜歡的順序消費(fèi)記錄。例如,消費(fèi)者可以重置為較早的偏移量以重新處理過(guò)去的數(shù)據(jù),或者跳至最近的記錄并從“現(xiàn)在”開始消費(fèi)。
這些功能的組合意味著Kafka的消費(fèi)者非常輕便 - 他們可以來(lái)來(lái)去去,對(duì)集群或其他消費(fèi)者沒(méi)有太大的影響。例如,您可以使用我們的命令行工具來(lái)“tail”任何主題的內(nèi)容,而不會(huì)更改任何現(xiàn)有消費(fèi)者使用的內(nèi)容。
日志中的分區(qū)有幾個(gè)用途。 首先,它們?cè)试S日志的大小超出適合單個(gè)服務(wù)器的存儲(chǔ)限制。 每個(gè)單獨(dú)的分區(qū)必須適合存放它的服務(wù)器,但是一個(gè)主題可能有許多分區(qū),因此它可以處理任意數(shù)量的數(shù)據(jù)。 其次,更重要的是,它們是作為并行處理的單位。
分布式
日志的所有有分區(qū)被分發(fā)到集群中的服務(wù)器上,每個(gè)服務(wù)器處理全部分區(qū)中的部分分區(qū)數(shù)據(jù)和請(qǐng)求。為了容錯(cuò),每個(gè)分區(qū)都被復(fù)制到一定數(shù)量(可配置)的不同服務(wù)器上。
每個(gè)分區(qū)(有多個(gè)副本)都有一臺(tái)服務(wù)器作為“l(fā)eader”,大于等于0臺(tái)服務(wù)器做為”followers”?!眑eader”服務(wù)器處理分區(qū)的所有讀寫操作?!眆ollowers”服務(wù)器對(duì)當(dāng)前分區(qū)做為旁觀者,什么都不做。當(dāng)”leader”服務(wù)器不可用時(shí),那么”followers”中的一臺(tái)將自動(dòng)成為”leader”。每臺(tái)服務(wù)器都即做為一些分區(qū)的”leader”,又做為其它分區(qū)的“followers”。
生產(chǎn)者
生產(chǎn)者向所選的主題發(fā)布數(shù)據(jù)。生產(chǎn)者負(fù)責(zé)選擇哪些消息應(yīng)該分配到主題內(nèi)的哪個(gè)分區(qū)。這種選擇分區(qū)方式,可以使用簡(jiǎn)單的循環(huán)方式來(lái)負(fù)載均衡; 也可以通過(guò)一些語(yǔ)義分區(qū)函數(shù)實(shí)現(xiàn)(如:基于消息的key的hash等),更多的是第二種情況來(lái)使用分區(qū)。
消費(fèi)者
傳統(tǒng)的消息處理有兩種模型:隊(duì)列和發(fā)布訂閱。隊(duì)列模式,消費(fèi)者池中的消費(fèi)者可以從一臺(tái)服務(wù)器讀數(shù)據(jù),并且每個(gè)消息只被其中一個(gè)消費(fèi)者消費(fèi)。發(fā)布訂閱模式,消息通過(guò)廣播方式發(fā)送給所有消費(fèi)者。kafka提供了一個(gè)單一的抽象概念,可以滿足這兩種(隊(duì)列、發(fā)布訂閱)模式--消費(fèi)者組。
消費(fèi)者通過(guò)分組名(group name)標(biāo)識(shí)自己,每條消息被發(fā)布到主題,并只會(huì)分發(fā)給消費(fèi)者組中的 唯一個(gè) 消費(fèi)者實(shí)例(即只被組中的一個(gè)消費(fèi)者消費(fèi))。這些消費(fèi)者即可以是同一臺(tái)服務(wù)器上不同的進(jìn)程,也可以是位于不同服務(wù)器上進(jìn)程。
如果所有的消費(fèi)者實(shí)例屬于同一分組(相同的分組名),那么這就是傳統(tǒng)的隊(duì)列模式(相同topic,只有一個(gè)消費(fèi)者能搶到消息)。
如果所有的消費(fèi)者實(shí)例不屬于同一分組,那么這就是發(fā)布訂閱模式(每個(gè)消費(fèi)者都能收到消息)

兩個(gè)服務(wù)器Kafka集群管理四個(gè)分區(qū)(P0-P3)與兩個(gè)消費(fèi)者組。消費(fèi)者組A有兩個(gè)消費(fèi)者實(shí)例,而組B有四個(gè)消費(fèi)者實(shí)例。
然而,更普遍的是,topic只有少量的消費(fèi)組,每個(gè)“邏輯訂閱者”都有一個(gè)消費(fèi)組。每個(gè)組由許多消費(fèi)者實(shí)例組成,具有可擴(kuò)展性和容錯(cuò)性。這就是發(fā)布-訂閱模式,訂閱者是一群消費(fèi)者而不是一個(gè)進(jìn)程。
傳統(tǒng)隊(duì)列維護(hù)消息順序性。如果多個(gè)消費(fèi)者從隊(duì)列中消費(fèi)消息,那么服務(wù)器以存儲(chǔ)的順序分發(fā)消息。雖然消息從服務(wù)器出隊(duì)列是按順序的,但是被分發(fā)給消費(fèi)者時(shí),是通過(guò)異步的方式,因此消息到達(dá)不同消費(fèi)者時(shí)可能是亂序的。這意味者并發(fā)消費(fèi)時(shí),消費(fèi)是亂序的。消息系統(tǒng)為了做到這點(diǎn),會(huì)采用只有一個(gè)消費(fèi)者消費(fèi)的理念,但這也意味是無(wú)法并行操作。
kafka這點(diǎn)做的更好,通過(guò)稱為分區(qū)(主題內(nèi))的并行概念,kafka即可以提供順序又可以負(fù)載均衡。這是通過(guò)給主題內(nèi)的相同分組下的消費(fèi)者提供多個(gè)分區(qū)的架構(gòu),來(lái)實(shí)現(xiàn)每個(gè)分區(qū)只能被一個(gè)消費(fèi)者消費(fèi)。通過(guò)這種方式,可以確保同一分區(qū)只有一個(gè)消費(fèi)者,因此一個(gè)分區(qū)消費(fèi)消息是順序的; 同時(shí),由于有多個(gè)分區(qū),因此可以負(fù)載均衡。注意:一個(gè)分組內(nèi),消費(fèi)者數(shù)量不能多于分區(qū)數(shù)量。此處的:不能多于,不是絕對(duì)。即:一個(gè)應(yīng)用集群(有消費(fèi)者)可能遠(yuǎn)遠(yuǎn)多于分區(qū)數(shù)量,只能說(shuō)超出的消費(fèi)者永遠(yuǎn)都無(wú)分區(qū)消費(fèi),但并不影響其它消費(fèi)者正常使用。
kafka僅僅支持分區(qū)內(nèi)的消息順序消費(fèi),并不支持全局(同一主題的不同分區(qū)之間)的消息順序。每個(gè)分區(qū)排序與根據(jù)消息key進(jìn)行數(shù)據(jù)分區(qū)的能力相結(jié)合,足以滿足大多數(shù)應(yīng)用程序的需求。 但是,如果你需要一個(gè)全局順序消費(fèi)消息,你可以通過(guò)一個(gè)主題只有一個(gè)分區(qū)的方法實(shí)現(xiàn),但是這也意味著一個(gè)分組只有一消費(fèi)者。
保證
一個(gè)高級(jí)的kafka提供以下保證:
- 由生產(chǎn)者發(fā)送到特定主題分區(qū)的消息將按照它們發(fā)送的順序添加。 也就是說(shuō),如果記錄M1和記錄M2由同一個(gè)生產(chǎn)者發(fā)送,并且M1被首先發(fā)送,則M1將具有比M2更低的偏移量值并且出現(xiàn)在日志中較早的地方。
- 消費(fèi)者實(shí)例按照存儲(chǔ)在日志中的順序查看記錄。
- 對(duì)于具有復(fù)制因子(replication factor)N的主題,我們將容忍多達(dá)N-1個(gè)服務(wù)器故障,而不會(huì)丟失任何提交給日志的記錄。
有關(guān)這些保證的更多細(xì)節(jié)在文檔的設(shè)計(jì)章節(jié)。
kafka作為消息系統(tǒng)
Kafka的流概念如何與傳統(tǒng)的企業(yè)消息系統(tǒng)相比較?
消息傳統(tǒng)上有兩種模式:隊(duì)列和發(fā)布-訂閱。在隊(duì)列中,消費(fèi)者池可以從服務(wù)器讀取并且每條消息只去往其中的一個(gè);在發(fā)布-訂閱中消息被廣播給所有消費(fèi)者。這兩種模式都有其優(yōu)點(diǎn)和缺點(diǎn)。隊(duì)列的優(yōu)勢(shì)在于它允許您將數(shù)據(jù)處理劃分為多個(gè)消費(fèi)者實(shí)例,這樣可以擴(kuò)展處理。不幸的是,隊(duì)列不是多訂閱的,一旦一個(gè)進(jìn)程讀取了數(shù)據(jù)它就消失了。發(fā)布-訂閱允許您將數(shù)據(jù)廣播到多個(gè)進(jìn)程,但無(wú)法進(jìn)行擴(kuò)展處理,因?yàn)槊織l消息都發(fā)送給每個(gè)訂閱者。
Kafka的消費(fèi)群體概念包含了這兩個(gè)概念。與隊(duì)列一樣,消費(fèi)者組允許您將一系列流程(消費(fèi)者組的成員)的處理分開。與發(fā)布-訂閱一樣,Kafka允許您向多個(gè)消費(fèi)者群體廣播消息。
Kafka模型的優(yōu)點(diǎn)是每個(gè)主題都具有這些屬性 - 它可以擴(kuò)展處理,也可以是多訂閱 - topic不需要選擇其中一個(gè)。
Kafka也比傳統(tǒng)的消息系統(tǒng)有更強(qiáng)的順序保證。
傳統(tǒng)隊(duì)列在服務(wù)器上按順序保留記錄,并且如果多個(gè)消費(fèi)者從隊(duì)列中消費(fèi),則服務(wù)器按照它們存儲(chǔ)的順序取出記錄。但是,雖然服務(wù)器按順序取出記錄,但是記錄是異步傳遞給消費(fèi)者的,所以不同的消費(fèi)者可能不是按照順序收到消息。這實(shí)際上意味著記錄的排序在并行消耗的情況下丟失。消息傳遞系統(tǒng)通常具有“排他消費(fèi)者”的屬性,只允許一個(gè)進(jìn)程從隊(duì)列中消耗,但這當(dāng)然意味著在處理中沒(méi)有并行處理能力。
Kafka做得更好。 通過(guò)在主題內(nèi)部有一個(gè)并行的概念 - 分區(qū),Kafka能夠提供排序保證和負(fù)載平衡。 這是通過(guò)將主題中的分區(qū)分配給使用者組中的使用者來(lái)實(shí)現(xiàn)的,以便每個(gè)分區(qū)僅由組中的一個(gè)使用者使用。 通過(guò)這樣做,我們確保消費(fèi)者是該分區(qū)的唯一消費(fèi)者,并按順序使用這些數(shù)據(jù)。 由于有很多分區(qū),這仍然可以平衡許多消費(fèi)者實(shí)例的負(fù)載。 但請(qǐng)注意,消費(fèi)群組中的消費(fèi)者實(shí)例不能多于分區(qū)。
卡夫卡作為存儲(chǔ)系統(tǒng)
任何允許將消息發(fā)布出去的消息隊(duì)列都可以充當(dāng)存儲(chǔ)系統(tǒng)。 Kafka的不同之處在于它是一個(gè)非常好的存儲(chǔ)系統(tǒng)。
數(shù)據(jù)寫入kafka時(shí)被寫入到磁盤, 并復(fù)制到其他服務(wù)器上進(jìn)行容錯(cuò), kafka允許生產(chǎn)者只有在消息已經(jīng)復(fù)制完, 并存儲(chǔ)后才得到寫成功的通知, 否則就認(rèn)為失敗.
kafka也很有效率利用了磁盤結(jié)構(gòu)–無(wú)論你存儲(chǔ)的是50KB或50TB的數(shù)據(jù)在kafka上, kafka都會(huì)有同樣的性能
由于嚴(yán)謹(jǐn)?shù)目紤]存儲(chǔ)并允許客戶端控制其讀取位置,所以可以將Kafka視為專用于高性能,低延遲提交日志存儲(chǔ),復(fù)制和傳播的專用分布式文件系統(tǒng)。
kafka作為數(shù)據(jù)流處理
只讀取,寫入和存儲(chǔ)數(shù)據(jù)流是不夠的,目的是允許流的實(shí)時(shí)處理。
kafka的流數(shù)據(jù)處理器是持續(xù)從輸入的topic讀取連續(xù)的數(shù)據(jù)流, 進(jìn)行數(shù)據(jù)處理, 轉(zhuǎn)換, 后產(chǎn)生連續(xù)的數(shù)據(jù)流輸出到topic中
例如,零售應(yīng)用程序可能會(huì)接受輸入的銷售和發(fā)貨流,并輸出一系列重排序的數(shù)據(jù)并針對(duì)這些數(shù)據(jù)的計(jì)算進(jìn)行價(jià)格調(diào)整。
直接使用生產(chǎn)者和消費(fèi)者API可以做簡(jiǎn)單的處理。但是對(duì)于更復(fù)雜的轉(zhuǎn)換,Kafka提供了一個(gè)完全集成的Streams API。這允許構(gòu)建應(yīng)用程序進(jìn)行非一般的處理,從而對(duì)流進(jìn)行聚合或者join另外一個(gè)流。
這個(gè)工具有助于解決這類應(yīng)用程序面臨的難題:處理亂序數(shù)據(jù),重新處理代碼更改的輸入,執(zhí)行有狀態(tài)的計(jì)算等等。
流API基于Kafka提供的核心原函數(shù)構(gòu)建:它使用生產(chǎn)者和消費(fèi)者API進(jìn)行輸入,使用Kafka進(jìn)行有狀態(tài)存儲(chǔ),并在流處理器實(shí)例之間使用相同的組機(jī)制來(lái)實(shí)現(xiàn)容錯(cuò)。
整合
消息傳遞,存儲(chǔ)和流處理的這種組合可能看起來(lái)很不尋常,但對(duì)于Kafka作為一個(gè)流媒體平臺(tái)來(lái)說(shuō),這是非常重要的。
像HDFS這樣的分布式文件系統(tǒng)允許存儲(chǔ)用于批處理的靜態(tài)文件。這樣的系統(tǒng)可以有效地存儲(chǔ)和處理過(guò)去的歷史數(shù)據(jù)。
傳統(tǒng)的企業(yè)消息系統(tǒng)只允許處理在你訂閱之后到達(dá)的數(shù)據(jù),以這種方式構(gòu)建的應(yīng)用程序處理在將來(lái)到達(dá)的數(shù)據(jù)。
Kafka結(jié)合了這兩種功能,而且這兩種組合對(duì)于Kafka用作流應(yīng)用平臺(tái)以及流式傳輸數(shù)據(jù)管道都是至關(guān)重要的。
通過(guò)將存儲(chǔ)和低延遲訂閱相結(jié)合,流式應(yīng)用程序可以同樣的方式處理歷史和未來(lái)的數(shù)據(jù)。一個(gè)應(yīng)用可以處理歷史存儲(chǔ)的數(shù)據(jù), 也可以在讀到最后記錄后, 保持等待未來(lái)的數(shù)據(jù)進(jìn)行處理。這是流處理的概括概念,包括批處理以及消息驅(qū)動(dòng)的應(yīng)用程序。