1. Kafka介紹
Kafka是最初由Linkedin公司開發(fā),是一個(gè)分布式、分區(qū)的、多副本的、多生產(chǎn)者、多訂閱者,基于zookeeper協(xié)調(diào)的分布式日志系統(tǒng)(也可以當(dāng)做MQ系統(tǒng)),常見(jiàn)可以用于web/nginx日志、訪問(wèn)日志,消息服務(wù)等等,Linkedin于2010年貢獻(xiàn)給了Apache基金會(huì)并成為頂級(jí)開源項(xiàng)目。
主要應(yīng)用場(chǎng)景:日志收集系統(tǒng)和消息系統(tǒng)
Kafka主要設(shè)計(jì)目標(biāo)如下:
以時(shí)間復(fù)雜度為O(1)的方式提供消息持久化能力,即使對(duì)TB級(jí)以上數(shù)據(jù)也能保證常數(shù)時(shí)間的訪問(wèn)性能
高吞吐率。即使在非常廉價(jià)的商用機(jī)器上也能做到單機(jī)支持每秒100K條消息的傳輸
支持Kafka Server間的消息分區(qū),及分布式消息,同時(shí)保證每個(gè)partition內(nèi)的消息順序傳輸
同時(shí)支持離線數(shù)據(jù)處理和實(shí)時(shí)數(shù)據(jù)處理
-
支持在線水平擴(kuò)展
image-20210312102002488.png
有兩種主要消息傳遞模式:點(diǎn)對(duì)點(diǎn)傳遞模式、發(fā)布-訂閱模式。大部分消息系統(tǒng)選用發(fā)布-訂閱模式。
Kafka就是一種發(fā)布-訂閱模式。
對(duì)消息中間件,消息分推拉兩種模式。Kafka只有消息的拉取,沒(méi)有推送,可以通過(guò)輪詢實(shí)現(xiàn)消息的推送
Kafka 特性:
Kafka在一個(gè)或多個(gè)可以跨越多個(gè)數(shù)據(jù)中心的服務(wù)器上作為集群運(yùn)行。
Kafka集群集群中按照主題分類管理,一個(gè)主題可以有多個(gè)分區(qū),一個(gè)分區(qū)可以有多個(gè)副本分區(qū)
每個(gè)記錄由一個(gè)鍵,一個(gè)值和一個(gè)時(shí)間戳組成
Kafka四個(gè)核心API
-
Producer API
允許應(yīng)用程序?qū)⒂涗浟靼l(fā)布到一個(gè)或多個(gè)Kafka主題。
-
Consumer API
允許應(yīng)用程序訂閱一個(gè)或多個(gè)主題并處理為其生成的記錄流
-
Streams API
允許應(yīng)用程序充當(dāng)流處理器,使用一個(gè)或多個(gè)主題的輸入流,并生成一個(gè)或多個(gè)輸出主題的輸出流,從而有效地將輸入流換為輸出流
-
Connector API
允許構(gòu)建和運(yùn)行將Kafka主題鏈接到現(xiàn)有應(yīng)用程序或數(shù)據(jù)系統(tǒng)的可重用生產(chǎn)者或使用者
例如:關(guān)系數(shù)據(jù)庫(kù)的連接器可能會(huì)捕獲對(duì)表的所有更改
2. Kafka優(yōu)勢(shì)
-
高吞吐量
單機(jī)每秒處理幾十上百萬(wàn)的消息量。即使存儲(chǔ)了許多TB的消息,它也保持穩(wěn)定的性能。
-
高性能
單節(jié)點(diǎn)支持上千個(gè)客戶端,并保證零停機(jī)和零數(shù)據(jù)丟失。
-
持久化數(shù)據(jù)存儲(chǔ)
將消息持久化到磁盤,通過(guò)將數(shù)據(jù)持久化到硬盤以及replication防止數(shù)據(jù)丟失。
零拷貝
順序讀,順序?qū)?/p>
利用Linux的也緩存
-
分布式系統(tǒng),易于向外擴(kuò)展
所有的Producer、Broker和Consumer都會(huì)有多個(gè),均為分布式的。無(wú)須停機(jī)即可擴(kuò)展機(jī)器。多個(gè)Producer、Consumer可能是不同的應(yīng)用。
-
可靠性
Kafka是分布式,分區(qū)、復(fù)制和容錯(cuò)的。
-
客戶端狀態(tài)維護(hù)
消息被處理的狀態(tài)是在Consumer端維護(hù),而不是由Server端維護(hù)。當(dāng)失敗時(shí)能自動(dòng)平衡
支持online和offline的場(chǎng)景
-
支持多種客戶端語(yǔ)言
Kafka支持Java、.NET、PHP、Python等多種語(yǔ)言
3. Kafka應(yīng)用場(chǎng)景
-
日志收集
一個(gè)公司可以用Kafka收集各種服務(wù)的Log,通過(guò)Kafka以統(tǒng)一接口服務(wù)的方式開發(fā)給各種Consumer
-
消息系統(tǒng)
解耦生產(chǎn)者和消費(fèi)者、緩存消息等。
-
用戶活動(dòng)跟蹤
Kafka經(jīng)常被用來(lái)記錄Web用戶或者APP用戶的各種活動(dòng),如瀏覽網(wǎng)頁(yè),搜索,點(diǎn)擊等活動(dòng),這些活動(dòng)信息被各個(gè)服務(wù)發(fā)布到Kafka的Topic中,然后消費(fèi)者通過(guò)訂閱這些Topic來(lái)做實(shí)時(shí)的監(jiān)控分析,亦可保持到數(shù)據(jù)庫(kù)。
-
運(yùn)營(yíng)指標(biāo)
Kafka也經(jīng)常用來(lái)記錄運(yùn)營(yíng)監(jiān)控?cái)?shù)據(jù)。包括手機(jī)各種分布式應(yīng)用的數(shù)據(jù),生產(chǎn)各種操作集中反饋,比如報(bào)警和報(bào)告
-
流失處理
比如Spark Streaming 和Storm
4. 基本架構(gòu)
4.1 消息和批次
Kafka的數(shù)據(jù)單元稱為消息。可以把消息看成是數(shù)據(jù)庫(kù)里的一個(gè)數(shù)據(jù)行或一條記錄。消息由字節(jié)數(shù)組組成。
消息有鍵,鍵也是一個(gè)字節(jié)數(shù)組。當(dāng)消息以一種可控的方式寫入不同的分區(qū)時(shí),會(huì)用到鍵。
為了提高效率,消息被分批寫入Kafka。批次就是一組消息,這些消息屬于同一個(gè)主體和分區(qū)。
把消息分成批次可以減少網(wǎng)絡(luò)開銷。批次越大,單位時(shí)間內(nèi)處理的消息就越多,單個(gè)消息的傳輸時(shí)間就越長(zhǎng)。批次數(shù)據(jù)會(huì)被壓縮,這樣可以提升數(shù)據(jù)的傳輸和存儲(chǔ)能力,但是需要更多的計(jì)算處理。
4.2 模式
消息模式(schema)有許多可用的選項(xiàng),以便于理解。如JSON和XML,但是它缺乏強(qiáng)類型處理能力。Kafka的許多開發(fā)者喜歡使用Apache Avro。Avro提供了一種緊湊的序列化格式,模式和消息體分開。當(dāng)模式發(fā)生變化時(shí),不需要重新生成代碼,它還支持強(qiáng)類型和模式進(jìn)化,其版本即向前兼容,也向后兼容。
數(shù)據(jù)格式的一致性對(duì)Kafka很重要,因?yàn)樗讼⒆x寫操作之間的耦合性。
4.3 主體和分區(qū)
Kafka的消息通過(guò)主體進(jìn)行分類。主題可比是數(shù)據(jù)庫(kù)的表或者文件系統(tǒng)里的文件夾。主題可以被分為若干分區(qū),一個(gè)主題通過(guò)分區(qū)分布于Kafka集群中,提供了橫向擴(kuò)展的能力。

4.4 生產(chǎn)者和消費(fèi)者
生產(chǎn)者創(chuàng)建消息。消費(fèi)者消費(fèi)消息。
一個(gè)消費(fèi)被發(fā)布到一個(gè)特定的主題上。
生產(chǎn)者在默認(rèn)情況下把消息均衡地分布到主題的所有分區(qū)上:
1. 直接指定消息的分區(qū)
2. 根據(jù)消息的key散列取模得出分區(qū)
3. 輪詢指定分區(qū)
消費(fèi)者通過(guò)偏移量來(lái)區(qū)分已經(jīng)讀過(guò)的消息,從而消費(fèi)消息。
消費(fèi)者是消費(fèi)組的一部分。消費(fèi)組保證每個(gè)分區(qū)只能被一個(gè)消費(fèi)者使用,避免重復(fù)消費(fèi)。

4.5 Broker和集群
一個(gè)獨(dú)立的Kafka服務(wù)器稱為broker。broker接收來(lái)自生產(chǎn)者的消息,為消息設(shè)置偏移量,并提交消息到磁盤保存。broker為消費(fèi)者提供服務(wù),對(duì)讀取分區(qū)的請(qǐng)求作出響應(yīng),返回已經(jīng)提交到磁盤上的消息。單個(gè)broker可以輕松處理數(shù)千個(gè)分區(qū)以及每秒百萬(wàn)級(jí)的消息量

每個(gè)集群都有一個(gè)broker是集群控制器(自動(dòng)從集群的活躍成員中選舉處理)
控制器負(fù)責(zé)管理工作:
將分區(qū)分配給broker
監(jiān)控broker
集群中一個(gè)分區(qū)屬于一個(gè)broker,該broker稱為分區(qū)首領(lǐng)
一個(gè)分區(qū)可以分配給多個(gè)broker,此時(shí)會(huì)發(fā)送分區(qū)復(fù)制。
分區(qū)復(fù)制提供了消息冗余,高可用。副本分區(qū)不負(fù)責(zé)處理消息的讀寫。
4.6 核心概念
4.6.1 Producer
生產(chǎn)者創(chuàng)建消息。
該角色將消息發(fā)布到Kafka的Topic中。broker接收到生產(chǎn)者發(fā)送的消息后,broker將該消息追加到當(dāng)前用于追加數(shù)據(jù)的segment文件中。
一般情況下,一個(gè)消息會(huì)被發(fā)布到一個(gè)特定的主題上。
默認(rèn)情況下通過(guò)輪詢把消息均衡地分布到主題的所有分區(qū)上。
在某些情況下,生產(chǎn)者會(huì)把消息直接寫到指定的分區(qū)。這通常是通過(guò)消息鍵和分區(qū)器來(lái)實(shí)現(xiàn)的,分區(qū)器為鍵生成一個(gè)散列值,并將其映射到指定的分區(qū)上。這樣可以保證包含同一個(gè)鍵的消息會(huì)被寫到同一分區(qū)上。
生產(chǎn)者也可以使用自定義的分區(qū)器,根據(jù)不同的業(yè)務(wù)規(guī)則將消息映射到分區(qū)
4.6.2 Consumer
消費(fèi)者讀取消息。
消費(fèi)者訂閱一個(gè)或多個(gè)主題,并按照消息生成的順序讀取它們。
消費(fèi)者通過(guò)檢查消息的偏移量來(lái)區(qū)分已經(jīng)讀取過(guò)的消息。偏移量是另一種元數(shù)據(jù),它是一個(gè)不斷遞增的整數(shù)值,在創(chuàng)建消息時(shí),Kafka 會(huì)把它添加到消息里。在給定的分區(qū)里,每個(gè)消息的偏移量都是唯一的。消費(fèi)者把每個(gè)分區(qū)最后讀取的消息偏移量保存在Zookeeper或Kafka上,如果消費(fèi)者關(guān)閉或重啟,它的讀取狀態(tài)不會(huì)丟失。
消費(fèi)者是消費(fèi)組的一部分。群組保證每個(gè)分區(qū)只能被一個(gè)消費(fèi)者使用。
如果一個(gè)消費(fèi)者失效,消費(fèi)組里的其他消費(fèi)者可以接管失效消費(fèi)者的工作,再平衡,分區(qū)重新分配。

4.6.3 Broker
一個(gè)獨(dú)立的Kafka服務(wù)器被稱為broker
broker 為消費(fèi)者提供服務(wù),對(duì)讀取分區(qū)的請(qǐng)求作出響應(yīng),返回已經(jīng)提交到磁盤上的消息。
如果topic有N個(gè)partition,集群有N個(gè)broker,那么每個(gè)broker存儲(chǔ)該topic的一個(gè)partition。
如果topic有N個(gè)partition,集群有(N+M)個(gè)broker,那么其中有N個(gè)broker存儲(chǔ)該topic的一個(gè)partition,剩下的M個(gè)broker不存儲(chǔ)該topic的partition數(shù)據(jù)。
如果某個(gè)topic有N個(gè)partition,集群中broker數(shù)目少于N個(gè),那么一個(gè)broker存儲(chǔ)該topic的一個(gè)或多個(gè)partition。在實(shí)際生產(chǎn)環(huán)境中,盡量避免這種情況的發(fā)送,這種情況容易導(dǎo)致Kafka集群數(shù)據(jù)不均衡。
broker是集群的組成部分。每個(gè)集群都有一個(gè)broker同時(shí)充當(dāng)集群控制器的角色(自動(dòng)從集群的活躍成員中選舉出來(lái))。
控制器復(fù)制管理工作,包括將分區(qū)分配給broker和監(jiān)控broker
在集群中,一個(gè)分區(qū)從屬于一個(gè)broker,該broker被稱為分區(qū)的首領(lǐng)。

4.6.4 Topic
每條發(fā)布到Kafka集群的消息都有一個(gè)類別,這個(gè)類別被稱為一個(gè)Topic
物理上不同Topic的消息分開存儲(chǔ)。
主題就好比數(shù)據(jù)庫(kù)的表,尤其是分庫(kù)分表之后的邏輯表。
4.6.5 Partition
主題可以被分為若干個(gè)分區(qū),一個(gè)分區(qū)就是一個(gè)提交日志。
消息以追加的方式寫入分區(qū),然后以先入先出的順序讀取。
無(wú)法在整個(gè)主題范圍內(nèi)保證消息的順序,但可以保證消息在單個(gè)分區(qū)內(nèi)的順序。
Kafka通過(guò)分區(qū)來(lái)實(shí)現(xiàn)數(shù)據(jù)冗余和伸縮性。
在需要嚴(yán)格保證消息的消費(fèi)順序的場(chǎng)景下,需要將partition數(shù)目設(shè)為1

4.6.6 Replicas
Kafka 使用主題來(lái)組織數(shù)據(jù),每個(gè)主題被分為若干個(gè)分區(qū),每個(gè)分區(qū)有多個(gè)副本。那些副本被保存在broker上,每個(gè)broker可以保存成百上千個(gè)屬于不同主題和分區(qū)的副本。
副本有兩種類型
-
首領(lǐng)副本
每個(gè)分區(qū)都有一個(gè)首領(lǐng)副本。為了保證一致性,所有生產(chǎn)者請(qǐng)求和消費(fèi)者請(qǐng)求都會(huì)經(jīng)過(guò)這個(gè)副本。
-
跟隨者副本
首領(lǐng)意外的副本都是跟隨者副本。跟隨者副本不處理來(lái)自客戶端的請(qǐng)求,他們唯一的任務(wù)就是從首領(lǐng)那里復(fù)制消息,保持與首領(lǐng)一直的狀態(tài)。如果首領(lǐng)發(fā)生崩潰,其中的一個(gè)跟隨者會(huì)被提升為新首領(lǐng)。
4.6.7 Offset
4.6.7.1 生產(chǎn)者Offset
消息寫入的時(shí)候,每一個(gè)分區(qū)都有一個(gè)Offset,這個(gè)Offset就是生產(chǎn)者的Offset,同時(shí)也是這個(gè)分區(qū)的最新最大的offset。
有些時(shí)候沒(méi)有指定某一個(gè)分區(qū)的offset,這個(gè)工作kafka幫我們完成。

4.6.7.2 消費(fèi)者offset

這是某一個(gè)分區(qū)的offset情況,生產(chǎn)者寫入的offset是最新最大的值是12,而當(dāng)Consumer A進(jìn)行消費(fèi)時(shí),從0開始消費(fèi),一直消費(fèi)到9,消費(fèi)者的offset就記錄在9,Consumer B就記錄在11。等下一次他們?cè)賮?lái)消費(fèi)時(shí),他們可以選擇接著上一次的位置消費(fèi),當(dāng)然也可以選擇從頭消費(fèi),或者跳到最近的記錄從“現(xiàn)在”開始消費(fèi)。
4.8 副本
Kafka 通過(guò)副本保證高可用。副本分為首領(lǐng)副本(Leader)和跟隨者副本(Follower)。
跟隨者副本包括同步副本和不同步副本,在發(fā)生首領(lǐng)副本切換的時(shí)候,只有同步副本可以切換為首領(lǐng)副本。
4.8.1 AR
分區(qū)中的所有副本統(tǒng)稱為AR(Assigned Replicas)
AR=ISR + OSR
4.8.1.1 ISR
所有與leader副本保持一定程度同步的副本(包括Leader)組成ISR(In-Sync Replicas),ISR集合是AR集合中的一個(gè)子集。消息會(huì)先發(fā)送到leader副本,然后follower副本才能從leader副本中拉取消息進(jìn)行同步,同步期間內(nèi)follower副本相對(duì)于leader副本而言會(huì)有一定程度的滯后。前面所說(shuō)的“一定程度”是指可以忍受的滯后范圍,這個(gè)范圍可以通過(guò)參數(shù)進(jìn)行配置。
4.8.1.2 OSR
與leader副本同步滯后過(guò)多的副本(不包括leader)副本,組成OSR(Out-Sync Replicas)。在正常情況下,所有的follower副本都應(yīng)該與leader副本保持一定程度的同步,即AR=ISR,OSR集合為空
4.8.2 HW
HW是High Watermak的縮寫,俗稱高水位,它表示了一個(gè)特定消息的偏移量(offset),消費(fèi)者只能拉取到這個(gè)offset之前的消息。
4.8.3 LEO
LEO是 Log End Offset的縮寫,它表示了當(dāng)前日志文件中下一條待寫入消息的offset

