Kafka介紹與原理分析

kafka是什么?

簡介

Apache Kafka 是一款高吞吐量的分布式的基于發(fā)布/訂閱模式的消息系統(tǒng),主要應(yīng)用于大數(shù)據(jù)實時處理領(lǐng)域。它使用Scala和Java語言編寫,是一個基于Zookeeper系統(tǒng)的分布式發(fā)布訂閱消息系統(tǒng),該項目的設(shè)計初衷是為實時數(shù)據(jù)提供一個統(tǒng)一、高吞吐量、低等待的消息傳遞平臺。在0.10版本之前,Kafka只是一個消息系統(tǒng),主要用來解決應(yīng)用解耦、異步消息等問題。

kafka一般被稱為“分布式提交日志”或者“分布式流平臺”。文件系統(tǒng)或數(shù)據(jù)庫提交日志用來提供所有事務(wù)的持久記錄,通過重放這些日志可以重建系統(tǒng)的狀態(tài)。同樣地,Kafka 的數(shù)據(jù)是按照一定順序持久化保存的,可以按需讀取。此外,Kafka 的數(shù)據(jù)分布在整個系統(tǒng)里,具備數(shù)據(jù)故障保護(hù)和性能伸縮能力。

logo

核心能力

  • 高吞吐量:即使在非常廉價的商用機(jī)器上也能做到單機(jī)支持每秒數(shù)百萬消息的傳輸。使用延遲低至 2 毫秒的機(jī)器集群以網(wǎng)絡(luò)有限的吞吐量傳遞消息。

  • 消息持久化:以時間復(fù)雜度為O(1)的方式提供消息持久化能力,即使對TB級以上數(shù)據(jù)也能保證常數(shù)時間復(fù)雜度的訪問性能

  • 分布式:支持消息分區(qū)以及分布式消費(fèi),并保證分區(qū)內(nèi)的消息順序。

  • 伸縮性:系統(tǒng)可以隨著數(shù)據(jù)流的增長進(jìn)行橫向擴(kuò)展??蓪⑸a(chǎn)集群擴(kuò)展到多達(dá)一千個代理、每天數(shù)萬億條消息、PB 級數(shù)據(jù)、數(shù)十萬個分區(qū),彈性擴(kuò)展和收縮存儲和處理。

  • 跨平臺:支持不同技術(shù)平臺的客戶端(如Java、PHP、Python等)。

  • 實時性:支持實時數(shù)據(jù)處理和離線數(shù)據(jù)處理。

發(fā)布/訂閱模式

一對多,消費(fèi)者消費(fèi)數(shù)據(jù)之后不會清除消息

消息生產(chǎn)者(發(fā)布)將消息發(fā)布到 topic 中,同時有多個消息消費(fèi)者(訂閱)消費(fèi)該消息。和點對點方式不同,發(fā)布到 topic 的消息會被所有訂閱者消費(fèi)。

發(fā)布/訂閱模式

基礎(chǔ)架構(gòu)

img
  1. Producer : 消息生產(chǎn)者,負(fù)責(zé)向 Kafka 發(fā)送消息到broker中。一般情況下,一個消息會被發(fā)布到一個特定的主題上。生產(chǎn)者在默認(rèn)情況下把消息均衡地分布到主題的所有分區(qū)上,而并不關(guān)心特定消息會被寫到哪個分區(qū)。

  2. Consumer : 消息消費(fèi)者,向 Kafka broker 讀取消息的客戶端。消費(fèi)者訂閱一個或多個主題,并按照消息生成的順序讀取它們。消費(fèi)者通過檢查消息的偏移量來區(qū)分已經(jīng)讀取過的消息。

  3. Consumer Group (CG): 消費(fèi)者組,若干個Consumer組成的集合。 消費(fèi)者組內(nèi)每個消費(fèi)者負(fù)責(zé)消費(fèi)不同分區(qū)的數(shù)據(jù),一個分區(qū)只能由一個組內(nèi)消費(fèi)者消費(fèi);消費(fèi)者組之間互不影響。 所有的消費(fèi)者都屬于某個消費(fèi)者組,即消費(fèi)者組是邏輯上的一個訂閱者。

  4. Broker :經(jīng)紀(jì)人,一臺 獨立的Kafka 服務(wù)器就是一個 broker。broker 接收來自生產(chǎn)者的消息,為消息設(shè)置偏移量,并提交消息到磁盤保存。broker 為消費(fèi)者提供服務(wù),對讀取分區(qū)的請求作出響應(yīng),返回已經(jīng)提交到磁盤上的消息。一個集群由多個 broker 組成。一個 broker可以容納多個 topic。

  5. Topic : 主題,kafka中的消息都是通過主題進(jìn)行分類的,可以理解為一個隊列, 生產(chǎn)者和消費(fèi)者面向的都是一個 topic。主題可以被分為若干個分區(qū),一個分區(qū)就是一個提交日志。消息以追加的方式寫入分區(qū),然后以先入先出的順序讀取。

  6. Partition: 為了實現(xiàn)擴(kuò)展性,一個非常大的 topic 可以分布到多個 broker(即服務(wù)器)上,一個 topic 可以分為多個 partition,每個 partition 是一個有序的隊列。partition中的每條消息都會被分配一個有序的id(offset)。kafka只保證按一個partition中的順序?qū)⑾l(fā)給consumer,不保證一個topic的整體(多個partition間)的順序。;

  7. Replica: 副本(Replication),為保證集群中的某個節(jié)點發(fā)生故障時, 該節(jié)點上的 partition 數(shù)據(jù)不丟失,且 Kafka仍然能夠繼續(xù)工作, Kafka 提供了副本機(jī)制,一個 topic 的每個分區(qū)都有若干個副本,一個 leader 和若干個 follower。

  8. Leader: 每個分區(qū)多個副本的“主”,生產(chǎn)者發(fā)送數(shù)據(jù)的對象,以及消費(fèi)者消費(fèi)數(shù)據(jù)的對象都是 leader。

  9. Follower: 每個分區(qū)多個副本中的“從”,實時從 leader 中同步數(shù)據(jù),保持和 leader 數(shù)據(jù)的同步。 leader 發(fā)生故障時,某個 Follower 會成為新的 leader。

工作原理分析

生產(chǎn)消息流程

producer是消息的生產(chǎn)者,也就是數(shù)據(jù)的入口。producer在寫入數(shù)據(jù)的時候永遠(yuǎn)都是找leader,而不會直接將數(shù)據(jù)寫入follower中。

  1. producer推送消息前,會先從集群中獲取分區(qū)的leader信息。

  2. producer將消息推送給相應(yīng)的leader。

  3. leader將收到的消息追加到本地文件的末端,且每條都有自己的offset。

  4. follower主動的從leader中拉取消息進(jìn)行同步。

  5. follower將消息寫入到本地中,然后想leader發(fā)送ack。

  6. leader收到所有follower的ack后,確保同步完成,再向producer發(fā)送ack。producer收到ack后就會進(jìn)行下一輪的推送,否則重新推送消息。

副本數(shù)據(jù)同步策略

序號 方案 優(yōu)點 缺點
1 半數(shù)以上完成同步, 就發(fā)送 ack 延遲低 選舉新的 leader 時,容忍 n 臺節(jié)點的故障,需要 2n+1 個副本。(如果集群有2n+1臺機(jī)器,選舉leader的時候至少需要半數(shù)以上即n+1臺機(jī)器投票,那么能容忍的故障,最多就是n臺機(jī)器發(fā)生故障)容錯率:1/2
2 全部完成同步,才發(fā)送ack 選舉新的 leader 時, 容忍 n 臺節(jié)點的故障,需要 n+1 個副本(如果集群有n+1臺機(jī)器,選舉leader的時候只要有一個副本就可以了)容錯率:1 延遲高

Kafka 選擇了第二種方案,原因如下:

  1. 同樣為了容忍 n 臺節(jié)點的故障,第一種方案需要 2n+1 個副本,而第二種方案只需要 n+1 個副本,而 Kafka 的每個分區(qū)都有大量的數(shù)據(jù), 第一種方案會造成大量數(shù)據(jù)的冗余。

  2. 雖然第二種方案的網(wǎng)絡(luò)延遲會比較高,但網(wǎng)絡(luò)延遲對 Kafka 的影響較小。

文件存儲機(jī)制

img

由于生產(chǎn)者生產(chǎn)消息會不斷的追加數(shù)據(jù)到log文件末尾,為防止log文件過大導(dǎo)致數(shù)據(jù)定位效率低下,kafka采用了分片和索引機(jī)制,將每個partition分為多個segment。

每個segment對應(yīng)兩個文件“.index” 和 “.log”文件,這些文件位于一個文件夾下,該文件的命名規(guī)則為:topic名稱+分區(qū)序號。例如,first這個topic有3個分區(qū),分別為first-0、first-1、first-2。

00000000000000000000.index
00000000000000000000.log
00000000000000170410.index
00000000000000170410.log
00000000000000239430.index
00000000000000239430.log

index和log文件以當(dāng)前segment的第一條信息的offset命名。

".index"文件存儲大量的索引信息, ".log"文件存儲大量的數(shù)據(jù),索引中的元數(shù)據(jù)指向?qū)?yīng)數(shù)據(jù)文件中的message的物理偏移地址。

img

生產(chǎn)者

分區(qū)策略

分區(qū)原因

  • 方便在集群中擴(kuò)展,每個 Partition 可以通過調(diào)整以適應(yīng)它所在的機(jī)器,而一個 Topic 又可以有多個 Partition 組成,因此整個集群就可以適應(yīng)適合的數(shù)據(jù)了。

  • 可以提高并發(fā),因此可以以 Partition 為單位讀寫了。

分區(qū)原則

  1. 指明 partition 的情況下,直接將指明的值直接作為 partiton 值;

  2. 沒有指明 partition 值但有 key 的情況下,將 key 的 hash 值與 topic 的 partition 數(shù)進(jìn)行取余得到 partition 值;

  3. 既沒有 partition 值又沒有 key 值的情況下,第一次調(diào)用時隨機(jī)生成一個整數(shù)(后面每次調(diào)用在這個整數(shù)上自增),將這個值與 topic 可用的 partition 總數(shù)取余得到 partition值,也就是常說的 round-robin 算法。

AR、LSR、OSR

AR:分區(qū)中的所有副本統(tǒng)稱為AR(Assigned Repllicas)。

ISR:所有與leader副本保持一定程度同步的副本(包括Leader)組成ISR(In-Sync Replicas),ISR集合是AR集合中的一個子集。消息會先發(fā)送到leader副本,然后follower副本才能從leader副本中拉取消息進(jìn)行同步,同步期間內(nèi)follower副本相對于leader副本而言會有一定程度的滯后。

OSR:與leader副本同步滯后過多的副本(不包括leader)副本,組成OSR(Out-Sync Relipcas)

由此可見:AR=ISR+OSR。在正常情況下,所有的follower副本都應(yīng)該與leader副本保持一定程度的同步,即AR=ISR,OSR集合為空。

Leader副本負(fù)責(zé)維護(hù)和跟蹤ISR集合中所有的follower副本的滯后狀態(tài),當(dāng)follower副本落后太多或者失效時,leader副本會吧它從ISR集合中剔除。 如果OSR集合中follower副本“追上”了Leader副本,之后再ISR集合中的副本才有資格被選舉為leader,而在OSR集合中的副本則沒有機(jī)會(這個原則可以通過修改對應(yīng)的參數(shù)配置來改變)

AR=ISR+OSR

ack機(jī)制

對于某些不太重要的數(shù)據(jù),對數(shù)據(jù)的可靠性要求不是很高,能夠容忍數(shù)據(jù)的少量丟失,所以沒必要等 ISR 中的 follower 全部接收成功。

所以 Kafka 為用戶提供了三種可靠性級別,用戶根據(jù)對可靠性和延遲的要求進(jìn)行權(quán)衡,選擇以下的配置。

acks 參數(shù)配置

  • 0: producer 不等待 broker 的 ack,這一操作提供了一個最低的延遲, broker 一接收到還沒有寫入磁盤就已經(jīng)返回,當(dāng) broker 故障時有可能丟失數(shù)據(jù);

  • 1: producer 等待 broker 的 ack, partition 的 leader 落盤成功后返回 ack,如果在 follower同步成功之前 leader 故障,那么將會丟失數(shù)據(jù)

  • -1(all) : producer 等待 broker 的 ack, partition 的 leader 和 ISR 的follower 全部落盤成功后才返回 ack。但是如果在 follower 同步完成后, broker 發(fā)送 ack 之前, leader 發(fā)生故障,那么會造成數(shù)據(jù)重復(fù)。

助記:返A(chǔ)CK前,0無落盤,1落盤,-1全落盤,(落盤:消息存到本地)

數(shù)據(jù)一致性

  • LEO:(Log End Offset)每個副本的最后一個offset

  • HW:(High Watermark)高水位,指的是消費(fèi)者能見到的最大的 offset, ISR 隊列中最小的 LEO

水位一致

消息都正常同步的情況,leader和follower的水位一致,LEO和HW都保存一致。

producer寫入消息

producer現(xiàn)在往leader中寫入消息4和5,leader的LEO與follower發(fā)生不對稱。

follower同步消息

在消息寫入leader之后,follower會發(fā)送拉取請求來拉取消息4和消息5以進(jìn)行消息同步。其中在同步過程中,不同的 follower 的同步效率也不盡相同。在某一時刻follower1完全跟上了leader而follower2只同步了消息4,如此leader的LEO為6,follower1的LEO為6,follower2的LEO為5,那么當(dāng)前分區(qū)的HW取最小值4,此時消費(fèi)者可以消費(fèi)到offset為0至4之間的消息。

同步完成

當(dāng)所有的副本都成功寫入了消息3和消息4,整個分區(qū)的HW和LEO都變?yōu)?,因此消費(fèi)者可以消費(fèi)到offset為5的消息了。

follower 故障和 leader 故障

  • follower 故障:follower 發(fā)生故障后會被臨時踢出 ISR,待該 follower 恢復(fù)后, follower 會讀取本地磁盤記錄的上次的 HW,并將 log 文件高于 HW 的部分截取掉,從 HW 開始向 leader 進(jìn)行同步。等該 follower 的 LEO 大于等于該 Partition 的 HW,即 follower 追上 leader 之后,就可以重新加入 ISR 了。

  • leader 故障:leader 發(fā)生故障之后,會從 ISR 中選出一個新的 leader,之后,為保證多個副本之間的數(shù)據(jù)一致性, 其余的 follower 會先將各自的 log 文件高于 HW 的部分截掉,然后從新的 leader同步數(shù)據(jù)。

注意: 這只能保證副本之間的數(shù)據(jù)一致性,并不能保證數(shù)據(jù)不丟失或者不重復(fù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容