簡(jiǎn)介
Apache Kafaka 是一個(gè)分布式流平臺(tái)(distributed streaming platform)。
流平臺(tái)有以下三個(gè)主要功能:
- 發(fā)布和訂閱流中的數(shù)據(jù)(records),和消息隊(duì)列或者企業(yè)消息系統(tǒng)類似
- 以容錯(cuò)和持久的方式保存流中的數(shù)據(jù)
- 當(dāng)流中的數(shù)據(jù)出現(xiàn)時(shí)奏路,處理該流中的數(shù)據(jù)
Kafka主要有兩類用途:
- 構(gòu)建能讓系統(tǒng)或應(yīng)用之間可靠地獲取數(shù)據(jù)的實(shí)時(shí)流數(shù)據(jù)管道
- 構(gòu)建轉(zhuǎn)換或響應(yīng)流數(shù)據(jù)的實(shí)時(shí)流應(yīng)用
為了了解Kafka是如何實(shí)現(xiàn)上面的功能,讓我們自下而上更深入的探索Kafka的這些能力。
一些關(guān)鍵概念:
- Kafka以集群的方式運(yùn)行在一個(gè)或多個(gè)服務(wù)器上,這些服務(wù)器可以跨多個(gè)數(shù)據(jù)中心
- Kafka集群將流的數(shù)據(jù)(records)保存在名為 topics 的分類(categories)中
- 每條數(shù)據(jù)由鍵(Key)恋博、值(Value)和時(shí)間戳(Timestamp)組成
Kafka 有四個(gè)核心API:
- Producer API :該接口允許應(yīng)用發(fā)布一個(gè)流數(shù)據(jù)到一個(gè)或多個(gè) topics
- Consumer API :該接口允許應(yīng)用訂閱一個(gè)或多個(gè) topics 然后處理這些 topics 中的流數(shù)據(jù)
- Streams API :該接口允許應(yīng)用作為一個(gè) 流處理器(stream processor) ,從一個(gè)或多個(gè) topics 的輸入流中消費(fèi)數(shù)據(jù)私恬,然后轉(zhuǎn)換并生產(chǎn)數(shù)據(jù)到一個(gè)或多個(gè) topics 的輸出流中
- Connector API :該接口允許構(gòu)建和運(yùn)行可重用的生產(chǎn)者(Producer)或者消費(fèi)者(Consumer)债沮,這些生產(chǎn)者或消費(fèi)者講Kafka中的 topics 和現(xiàn)有的應(yīng)用或者數(shù)據(jù)系統(tǒng)(如數(shù)據(jù)庫(kù))連接起來(lái)。比如一個(gè) connector 可以連接到一個(gè)關(guān)系型數(shù)據(jù)庫(kù)從而可以捕捉到數(shù)據(jù)表中的任何變化本鸣,然后進(jìn)行響應(yīng)的處理
這些API的關(guān)系如下圖:
Kafka 使用一種簡(jiǎn)單疫衩、高效、語(yǔ)言無(wú)關(guān)的 TCP協(xié)議 來(lái)完成客戶端和服務(wù)端的數(shù)據(jù)交換荣德。這是一種版本化并且向后兼容的協(xié)議闷煤。Kafka 默認(rèn)提供了 Java 客戶端,并且也有大部分其他語(yǔ)言可用的客戶端涮瞻。
Topics 和 Logs
我們首先來(lái)看看 Kafka 對(duì)流數(shù)據(jù) ( a stream of records) 的提供的核心抽象 —— Topic
Topic 是數(shù)據(jù)被發(fā)布到 Kafka 的一個(gè)分類曹傀。Topics 可以有零個(gè)、一個(gè)或者多個(gè)消費(fèi)者(Consumers)饲宛,這些消費(fèi)訂閱(subscribe)被寫入 topics 的數(shù)據(jù)。
對(duì)每個(gè) topic嗜价, Kafka 集群維護(hù)了一個(gè)分區(qū)的記錄(log)艇抠,如下圖所示:
每一個(gè)分區(qū) (Partition) 都是一個(gè)有序的幕庐、不可變的數(shù)據(jù)序列,這些數(shù)據(jù)被不斷的添加到序列的尾部家淤,每個(gè)分區(qū)都是一種結(jié)構(gòu)化的 提交記錄 (commit log)异剥。 在分區(qū)中的每一條數(shù)據(jù)都被賦予了一個(gè)連續(xù)的數(shù)字ID,這個(gè)ID叫做 偏移量 (offset) 絮重。 偏移量唯一的標(biāo)識(shí)了每個(gè)分區(qū)中的每條數(shù)據(jù)冤寿。
Kafka 集群會(huì)持久化保存所有被發(fā)布到 topics 中的數(shù)據(jù)(無(wú)論這些數(shù)據(jù)是否已經(jīng)被消費(fèi)),數(shù)據(jù)的保存時(shí)間是可以配置的青伤。比如督怜,如果保留周期設(shè)置為兩天,那么一條數(shù)據(jù)被發(fā)布到 topic 以后狠角,在兩天內(nèi)都是可以被消費(fèi)的号杠,兩天以后會(huì)被 Kafka 丟棄以釋放磁盤空間。Kafka 的性能在數(shù)據(jù)大小方面是恒定的丰歌,所以長(zhǎng)時(shí)間的存儲(chǔ)數(shù)據(jù)不是問(wèn)題姨蟋。
實(shí)際上,每個(gè)消費(fèi)者 (Consumer) 唯一保留的數(shù)據(jù)就是該消費(fèi)者在記錄 (log) 中的偏移量 (offset)立帖。該偏移量由消費(fèi)者自身控制:一般情況下眼溶,消費(fèi)者會(huì)在讀取數(shù)據(jù)的時(shí)候線性地增加其偏移量,但實(shí)際上晓勇,由于偏移量是由消費(fèi)者自身控制堂飞,因此它可以按照自己喜歡的任何順序來(lái)消費(fèi)數(shù)據(jù) (records) 。比如宵蕉,消費(fèi)者可以把偏移量重置為以前的位置來(lái)重新處理過(guò)去的數(shù)據(jù)酝静,或者跳到最近的數(shù)據(jù)從“現(xiàn)在”開(kāi)始消費(fèi)。
這些功能的組合意味著 Kafka 的消費(fèi)者非常輕量級(jí)羡玛,他們可以隨意的運(yùn)行和停止而對(duì)集合或其他消費(fèi)者沒(méi)有太大影響别智。比如,你可以使用自帶的命令行工具的命令 tail 來(lái)獲取任何 topic 的內(nèi)容而不會(huì)改變現(xiàn)有的消費(fèi)者稼稿。
記錄(Log) 中的分區(qū)有幾個(gè)目的薄榛。第一個(gè)是允許 Log 擴(kuò)展到超過(guò)適合單個(gè)服務(wù)器的大小。第二個(gè)是每個(gè)分區(qū)的大小必須合適它所在的服務(wù)器让歼,但是一個(gè) topic 可以有許多分區(qū)敞恋,所以一個(gè) topic 可以有任意數(shù)量的數(shù)據(jù)。
分布式
記錄(Log) 的分區(qū)分布在 Kafka 集群的服務(wù)器中谋右,每個(gè)服務(wù)器處理數(shù)據(jù)并向分區(qū)的共享發(fā)起請(qǐng)求硬猫。每個(gè)分區(qū)都在數(shù)量可配置的服務(wù)器中進(jìn)行復(fù)制,以實(shí)現(xiàn)容錯(cuò)。
每個(gè)分區(qū)都有一個(gè)服務(wù)器作為 Leader啸蜜,其他服務(wù)器作為 Followers坑雅。 Leader 負(fù)責(zé)處理分區(qū)的所有讀寫請(qǐng)求,Followers 僅僅被動(dòng)地從 Leader 復(fù)制數(shù)據(jù)衬横。 如果 Leader 掛掉了裹粤,其中一個(gè) Followers 會(huì)自動(dòng)變成新的 Leader。每個(gè)服務(wù)器都扮演某些分區(qū)中的 Leader 和某些分區(qū)中的 Followers蜂林,所以負(fù)載在集群中得到了很好的均衡遥诉。
Producers
Producers 發(fā)布數(shù)據(jù)到它們選擇的 topics 中。 Producer 決定數(shù)據(jù)放到哪個(gè) topic 的哪個(gè)分區(qū)(Partition) 中噪叙“猓可以通過(guò)流行的 round-robin 來(lái)完成,也可以通過(guò)某些語(yǔ)義分區(qū)功能來(lái)實(shí)現(xiàn)构眯。
Consumers
Consumers 使用 Consumer group 的名字來(lái)標(biāo)識(shí)自己愕难,并且每個(gè)發(fā)布到 topic 的數(shù)據(jù) (record) 都會(huì)被傳遞到每個(gè) consumer group 中的 一個(gè) 消費(fèi)者實(shí)例。消費(fèi)者實(shí)例可以在單獨(dú)的進(jìn)行中或者在不同的機(jī)器中惫霸。
- 如果所有的消費(fèi)者實(shí)例都在同一個(gè) consumer group 中猫缭,那么數(shù)據(jù)將會(huì)輪流被組中的消費(fèi)者消費(fèi)。
- 如果所有的消費(fèi)者實(shí)例都在不同的 consumer group 中壹店,那么每一條數(shù)據(jù)都會(huì)被所有的消費(fèi)者消費(fèi)猜丹,即廣播。
一個(gè)有兩個(gè)服務(wù)器的 Kafka 集群硅卢,托管了四個(gè)分區(qū)(P0 - P3)射窒,包含了兩個(gè) consumer group,第一個(gè)組擁有兩個(gè)消費(fèi)者實(shí)例将塑,第二個(gè)組擁有四個(gè)消費(fèi)者實(shí)例脉顿。
然而,更常見(jiàn)的是点寥,每個(gè) topic 有少量的 consumer group艾疟, 每個(gè)組都由許多的消費(fèi)者實(shí)例組成,以實(shí)現(xiàn)可伸縮性和容錯(cuò)性敢辩。這和傳統(tǒng)的“發(fā)布-訂閱”模式?jīng)]有什么不同蔽莱,只不過(guò)訂閱者不是一個(gè)單獨(dú)的進(jìn)程,而是一個(gè)消費(fèi)者集群戚长。
在 Kafka 中實(shí)現(xiàn)消費(fèi)的方式是通過(guò)在消費(fèi)者實(shí)例劃分 Log 中的分區(qū)盗冷,這樣每個(gè)實(shí)例在任何時(shí)間都是“公平等分”的獨(dú)占消費(fèi)者。維護(hù)消費(fèi)者組中成員資格的過(guò)程是由 Kafka 自己的協(xié)議動(dòng)態(tài)處理的同廉。如果有新的實(shí)例加入到組中仪糖,新的實(shí)例將會(huì)接管一些其他成員的分區(qū)柑司;如果有實(shí)例掛掉了,該實(shí)例管理的分區(qū)將會(huì)被分給其他實(shí)例乓诽。
Kafka 只提供分區(qū)中的數(shù)據(jù)總記錄帜羊,而不是在不同 topic 不同分區(qū)之間的記錄。
多用戶
Kafka 可以被部署為多用戶解決方案鸠天。可以通過(guò)配置哪些 topic 可以生成或消費(fèi)數(shù)據(jù)來(lái)啟用多用戶功能帐姻。多用戶也支持配額稠集。管理員可以定義和強(qiáng)制執(zhí)行配額,以控制客戶端使用的 broker 資源饥瓷。
保證
Kafka 提供了以下保證:
- 生產(chǎn)者發(fā)送到某個(gè) topic 分區(qū)的消息將按照其發(fā)送的順序依次添加
- consumer 實(shí)例按照它們儲(chǔ)存在 log 中的順序查看數(shù)據(jù)
- 對(duì)于具有復(fù)制因子 N 的 topic剥纷,我們會(huì)允許最多 N - 1 個(gè)服務(wù)器故障,而不會(huì)丟失任何提交到 log 的數(shù)據(jù)
Kafka 作為消息系統(tǒng)(消息隊(duì)列)
Kafka的流概念與傳統(tǒng)的企業(yè)消息系統(tǒng)相比如何呢铆?
消息傳統(tǒng)上有兩種模型:隊(duì)列和發(fā)布 - 訂閱晦鞋。在隊(duì)列中,消費(fèi)者池可以從服務(wù)器讀取并處理數(shù)據(jù)個(gè);在發(fā)布 - 訂閱中棺克,數(shù)據(jù)被廣播給所有消費(fèi)者悠垛。這兩種模型中的每一種都有優(yōu)點(diǎn)和缺點(diǎn)。隊(duì)列的優(yōu)勢(shì)在于它允許在多個(gè)消費(fèi)者實(shí)例上處理數(shù)據(jù)娜谊,從而可以擴(kuò)展數(shù)據(jù)的處理确买。但是,隊(duì)列不是多用戶的纱皆,一旦一個(gè)消費(fèi)者讀取數(shù)據(jù)湾趾,該數(shù)據(jù)就被使用。發(fā)布 - 訂閱允許將數(shù)據(jù)廣播到多個(gè)訂閱者派草,但由于每條消息都發(fā)送給每個(gè)訂閱者搀缠,因此無(wú)法進(jìn)行擴(kuò)展處理。
Kafka 的消費(fèi)者組概念概括了傳統(tǒng)消息系統(tǒng)的兩個(gè)概念近迁。與隊(duì)列一樣艺普,消費(fèi)者組允許將數(shù)據(jù)處理劃分為一組進(jìn)程钳踊。與發(fā)布 - 訂閱一樣衷敌,Kafka 允許向多個(gè)消費(fèi)者組廣播消息。
Kafka 模型的優(yōu)勢(shì)在于每個(gè) topic 都具有這些屬性拓瞪,它可以擴(kuò)展數(shù)據(jù)處理并且也是多用戶的缴罗。
與傳統(tǒng)的消息系統(tǒng)相比,Kafka 有更強(qiáng)的順序保證祭埂。
傳統(tǒng)隊(duì)列在服務(wù)器上按順序保留記錄面氓,如果多個(gè)消費(fèi)者從隊(duì)列中消耗兵钮,則服務(wù)器按照存儲(chǔ)順序分發(fā)數(shù)據(jù)。但是舌界,雖然服務(wù)器按順序分發(fā)數(shù)據(jù)掘譬,但是數(shù)據(jù)是異步傳遞給消費(fèi)者的,因此它們可能會(huì)在不同的消費(fèi)者處出現(xiàn)問(wèn)題呻拌。這實(shí)際上意味著在存在并行消費(fèi)的情況下丟失數(shù)據(jù)的順序葱轩。消息系統(tǒng)通常通過(guò)具有“獨(dú)占消費(fèi)者”概念來(lái)解決這個(gè)問(wèn)題,該概念只允許一個(gè)進(jìn)程從隊(duì)列中消費(fèi)數(shù)據(jù)藐握,這樣就沒(méi)有了并行性靴拱。
在 Kafka 中。通過(guò)在 topic 中具有并行性概念 分區(qū) 猾普,Kafka 能夠在消費(fèi)者流程池中提供順序保證和負(fù)載均衡袜炕。這是通過(guò)將 topic 中的分區(qū)分配給消費(fèi)者組中的消費(fèi)者來(lái)實(shí)現(xiàn)的,以便每個(gè)分區(qū)僅由該組中的一個(gè)消費(fèi)者使用初家。這樣偎窘,就可以確保消費(fèi)者是該分區(qū)的唯一讀取者并按順序使用數(shù)據(jù)。由于有許多分區(qū)溜在,便可以平衡許多消費(fèi)者實(shí)例的負(fù)載陌知。但請(qǐng)注意,消費(fèi)者組中的消費(fèi)者實(shí)例不能超過(guò)分區(qū)炕泳。
Kafka 作為存儲(chǔ)系統(tǒng)
任何允許 發(fā)布與消費(fèi) 消息解耦的消息隊(duì)列纵诞,實(shí)際上扮演了一個(gè)消息的存儲(chǔ)系統(tǒng)。 Kafka的不同之處在于它是一個(gè)非常好的存儲(chǔ)系統(tǒng)培遵。
寫入 Kafka 的數(shù)據(jù)將寫入磁盤并進(jìn)行復(fù)制以實(shí)現(xiàn)容錯(cuò)浙芙。 Kafka 允許生產(chǎn)者等待確認(rèn),以便在完全復(fù)制之前寫入認(rèn)為是不完整的籽腕,直到數(shù)據(jù)全部復(fù)制到所有服務(wù)器上嗡呼。
Kafka 的磁盤結(jié)構(gòu)很好地使用了伸縮,無(wú)論服務(wù)器上有50 KB還是50 TB的數(shù)據(jù)皇耗,Kafka 的磁盤性能影響都差不多南窗。
Kafka 是一種專用于高性能,低延遲提交日志(commoit log)存儲(chǔ)郎楼,復(fù)制和傳播的專用分布式文件系統(tǒng)万伤。