1. Kafka概述
1.1 定義
Kafka 是由 Apache 軟件基金會開發(fā)的一個開源流處理平臺。
Kafka 是一個分布式的基于發(fā)布/訂閱模式的消息隊(duì)列(Message Queue),主要應(yīng)用于大數(shù)據(jù)實(shí)時處理領(lǐng)域。
1.2 消息隊(duì)列
1.2.1 傳統(tǒng)消息隊(duì)列的應(yīng)用場景
1.2.2 為什么需要消息隊(duì)列
解耦:允許你獨(dú)立的擴(kuò)展或修改兩邊的處理過程,只要確保它們遵守同樣的接口約束。
冗余:消息隊(duì)列把數(shù)據(jù)進(jìn)行持久化直到它們已經(jīng)被完全處理,通過這一方式規(guī)避了數(shù)據(jù)丟失風(fēng)險(xiǎn)。許多消息隊(duì)列所采用的"插入-獲取-刪除"范式中,在把一個消息從隊(duì)列中刪除之前,需要你的處理系統(tǒng)明確的指出該消息已經(jīng)被處理完畢,從而確保你的數(shù)據(jù)被安全的保存直到你使用完畢。
擴(kuò)展性:因?yàn)橄㈥?duì)列解耦了你的處理過程,所以增大消息入隊(duì)和處理的頻率是很容易的,只要另外增加處理過程即可。
靈活性 & 峰值處理能力:在訪問量劇增的情況下,應(yīng)用仍然需要繼續(xù)發(fā)揮作用,但是這樣的突發(fā)流量并不常見。如果以能處理這類峰值訪問為標(biāo)準(zhǔn)來投入資源隨時待命無疑是巨大的浪費(fèi)。使用消息隊(duì)列能夠使關(guān)鍵組件頂住突發(fā)的訪問壓力,而不會因?yàn)橥话l(fā)的超負(fù)荷的請求而完全崩潰。
可恢復(fù)性:系統(tǒng)的一部分組件失效時,不會影響到整個系統(tǒng)。消息隊(duì)列降低了進(jìn)程間的耦合度,所以即使一個處理消息的進(jìn)程掛掉,加入隊(duì)列中的消息仍然可以在系統(tǒng)恢復(fù)后被處理。
順序保證:在大多使用場景下,數(shù)據(jù)處理的順序都很重要。大部分消息隊(duì)列本來就是排序的,并且能保證數(shù)據(jù)會按照特定的順序來處理。(Kafka 保證一個 Partition 內(nèi)的消息的有序性)
緩沖:有助于控制和優(yōu)化數(shù)據(jù)流經(jīng)過系統(tǒng)的速度, 解決生產(chǎn)消息和消費(fèi)消息的處理速度不一致的情況。
異步通信:很多時候,用戶不想也不需要立即處理消息。消息隊(duì)列提供了異步處理機(jī)制,允許用戶把一個消息放入隊(duì)列,但并不立即處理它。想向隊(duì)列中放入多少消息就放多少,然后在需要的時候再去處理它們。
1.2.3 消息隊(duì)列的兩種模式
點(diǎn)對點(diǎn)模式(一對一,消費(fèi)者主動拉取數(shù)據(jù),收到后消息清除)
消息生產(chǎn)者生產(chǎn)消息發(fā)送到 Queue 中,然后消費(fèi)者從 Queue 中取出并且消費(fèi)消息。消息被消費(fèi)以后,queue 中不再有存儲,所以消息消費(fèi)者不可能消費(fèi)到已經(jīng)被消費(fèi)的消息。Queue 支持存在多個消費(fèi)者,但是對一個消息而言,只會有一個消費(fèi)者可以消費(fèi)。
發(fā)布/訂閱模式(一對多,數(shù)據(jù)生產(chǎn)后,推送給所有訂閱者)
消息生產(chǎn)者(發(fā)布)將消息發(fā)布到 topic 中,同時有多個消息消費(fèi)者(訂閱)消費(fèi)該消息。和點(diǎn)對點(diǎn)方式不同,發(fā)布到 topic 的消息會被所有訂閱者消費(fèi)。
1.3 Kafka 基礎(chǔ)架構(gòu)圖
Producer :消息生產(chǎn)者,就是向 kafka broker 發(fā)消息的客戶端;
Consumer :消息消費(fèi)者,向 kafka broker 取消息的客戶端;
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)者組是邏輯上的一個訂閱者。
Broker :一臺 kafka 服務(wù)器就是一個 broker(雖然多個 Broker 進(jìn)程能夠運(yùn)行在同一臺機(jī)器上,但更常見的做法是將不同的 Broker 分散運(yùn)行在不同的機(jī)器上)。一個集群由多個 broker 組成。一個 broker 可以容納多個 topic;
Topic :可以理解為一個隊(duì)列,Kafka 的消息通過 Topics(主題) 進(jìn)行分類,生產(chǎn)者和消費(fèi)者面向的都是一個 topic;
Partition:為了實(shí)現(xiàn)擴(kuò)展性,一個非常大的 topic 可以分布到多個 broker(即服務(wù)器)上, 一個 topic 可以分為多個 partition,每個 partition 是一個有序的隊(duì)列;partition 中的每條消息都會被分配一個有序的 id( offset)。kafka 只保證按一個 partition 中的順序?qū)⑾l(fā)給 consumer,不保證一個 topic 的整體(多個 partition 間)的順序;
Replica:副本,為保證集群中的某個節(jié)點(diǎn)發(fā)生故障時,該節(jié)點(diǎn)上的 partition 數(shù)據(jù)不丟失,且 kafka 仍然能夠繼續(xù)工作,kafka 提供了副本機(jī)制,一個 topic 的每個分區(qū)都有若干個副本, 一個 leader 和若干個 follower;
leader:每個分區(qū)多個副本的“主”,生產(chǎn)者發(fā)送數(shù)據(jù)的對象,以及消費(fèi)者消費(fèi)數(shù)據(jù)的對象都是 leader;
follower:每個分區(qū)多個副本中的“從”,實(shí)時從 leader 中同步數(shù)據(jù),保持和 leader 數(shù)據(jù)的同步。leader 發(fā)生故障時,某個 follower 會成為新的 follower;
offset:kafka 的存儲文件都是按照offset.kafka來命名,用 offset 做名字的好處是方便查找。例如你想找位于 2049 的位置,只要找到 2048.kafka 的文件即可。當(dāng)然 the first offset 就是 00000000000.kafka。
2. Hello Kafka
2.1 動起手來
Quickstart
中文版入門指南
2.2 基本概念(官方介紹翻譯)
Kafka 是一個分布式的流處理平臺。是支持分區(qū)的(partition)、多副本的(replica),基于 ZooKeeper 協(xié)調(diào)的分布式消息系統(tǒng),它的最大的特性就是可以實(shí)時的處理大量數(shù)據(jù)以滿足各種需求場景:比如基于 hadoop 的批處理系統(tǒng)、低延遲的實(shí)時系統(tǒng)、storm/Spark 流式處理引擎,web/nginx 日志、訪問日志,消息服務(wù)等等
有三個關(guān)鍵能力
它可以讓你發(fā)布和訂閱記錄流。在這方面,它類似于一個消息隊(duì)列或企業(yè)消息系統(tǒng)
它可以讓你持久化收到的記錄流,從而具有容錯能力
它可以讓你處理收到的記錄流
應(yīng)用于兩大類應(yīng)用
構(gòu)建實(shí)時的流數(shù)據(jù)管道,可靠地獲取系統(tǒng)和應(yīng)用程序之間的數(shù)據(jù)。
構(gòu)建實(shí)時流的應(yīng)用程序,對數(shù)據(jù)流進(jìn)行轉(zhuǎn)換或反應(yīng)。
想要了解 Kafka 如何具有這些能力,首先,明確幾個概念:
Kafka 作為一個集群運(yùn)行在一個或多個服務(wù)器上
Kafka 集群存儲的消息是以主題(topics)為類別記錄的
每個消息記錄包含一個鍵,一個值和時間戳
Kafka有五個核心API:
Producer API允許應(yīng)用程序發(fā)布記錄流至一個或多個 Kafka 的話題(Topics)
Consumer API允許應(yīng)用程序訂閱一個或多個主題,并處理這些主題接收到的記錄流
Streams API允許應(yīng)用程序充當(dāng)流處理器(stream processor),從一個或多個主題獲取輸入流,并生產(chǎn)一個輸出流至一個或多個的主題,能夠有效地變換輸入流為輸出流
Connector API允許構(gòu)建和運(yùn)行可重用的生產(chǎn)者或消費(fèi)者,能夠把 Kafka 主題連接到現(xiàn)有的應(yīng)用程序或數(shù)據(jù)系統(tǒng)。例如,一個連接到關(guān)系數(shù)據(jù)庫的連接器(connector)可能會獲取每個表的變化
Admin API允許管理和檢查主題、brokes 和其他 Kafka 對象。(這個是新版本才有的)
Kafka 的客戶端和服務(wù)器之間的通信是靠一個簡單的,高性能的,與語言無關(guān)的 TCP 協(xié)議完成的。這個協(xié)議有不同的版本,并保持向后兼容舊版本。Kafka 不光提供了一個 Java 客戶端,還有許多語言版本的客戶端。
主題和日志
主題是同一類別的消息記錄(record)的集合。Kafka 的主題支持多用戶訂閱,也就是說,一個主題可以有零個,一個或多個消費(fèi)者訂閱寫入的數(shù)據(jù)。對于每個主題,Kafka 集群都會維護(hù)一個分區(qū)日志,如下所示:
每個分區(qū)是一個有序的,不可變的消息序列,新的消息不斷追加到 partition 的末尾。在每個 partition 中,每條消息都會被分配一個順序的唯一標(biāo)識,這個標(biāo)識被稱為offset,即偏移量。kafka 不能保證全局有序,只能保證分區(qū)內(nèi)有序。
Kafka 集群保留所有發(fā)布的記錄,不管這個記錄有沒有被消費(fèi)過,Kafka 提供可配置的保留策略去刪除舊數(shù)據(jù)(還有一種策略根據(jù)分區(qū)大小刪除數(shù)據(jù))。例如,如果將保留策略設(shè)置為兩天,在數(shù)據(jù)發(fā)布后兩天,它可用于消費(fèi),之后它將被丟棄以騰出空間。Kafka 的性能跟存儲的數(shù)據(jù)量的大小無關(guān)(會持久化到硬盤), 所以將數(shù)據(jù)存儲很長一段時間是沒有問題的。
事實(shí)上,在單個消費(fèi)者層面上,每個消費(fèi)者保存的唯一的元數(shù)據(jù)就是它所消費(fèi)的數(shù)據(jù)日志文件的偏移量。偏移量是由消費(fèi)者來控制的,通常情況下,消費(fèi)者會在讀取記錄時線性的提高其偏移量。不過由于偏移量是由消費(fèi)者控制,所以消費(fèi)者可以將偏移量設(shè)置到任何位置,比如設(shè)置到以前的位置對數(shù)據(jù)進(jìn)行重復(fù)消費(fèi),或者設(shè)置到最新位置來跳過一些數(shù)據(jù)。
分布式
日志的分區(qū)會跨服務(wù)器的分布在 Kafka 集群中,每個服務(wù)器會共享分區(qū)進(jìn)行數(shù)據(jù)請求的處理。每個分區(qū)可以配置一定數(shù)量的副本分區(qū)提供容錯能力。
每個分區(qū)都有一個服務(wù)器充當(dāng)“l(fā)eader”和零個或多個服務(wù)器充當(dāng)“followers”。leader 處理所有的讀取和寫入分區(qū)的請求,而 followers 被動的從領(lǐng)導(dǎo)者拷貝數(shù)據(jù)。如果 leader 失敗了,followers 之一將自動成為新的領(lǐng)導(dǎo)者。每個服務(wù)器可能充當(dāng)一些分區(qū)的 leader 和其他分區(qū)的 follower,所以 Kafka 集群內(nèi)的負(fù)載會比較均衡。
生產(chǎn)者
生產(chǎn)者發(fā)布數(shù)據(jù)到他們所選擇的主題。生產(chǎn)者負(fù)責(zé)選擇把記錄分配到主題中的哪個分區(qū)。這可以使用輪詢算法( round-robin)進(jìn)行簡單地平衡負(fù)載,也可以根據(jù)一些更復(fù)雜的語義分區(qū)算法(比如基于記錄一些鍵值)來完成。
消費(fèi)者
消費(fèi)者以消費(fèi)群(consumer group)的名稱來標(biāo)識自己,每個發(fā)布到主題的消息都會發(fā)送給訂閱了這個主題的消費(fèi)群里面的一個消費(fèi)者的一個實(shí)例。消費(fèi)者的實(shí)例可以在單獨(dú)的進(jìn)程或單獨(dú)的機(jī)器上。
如果所有的消費(fèi)者實(shí)例都屬于相同的消費(fèi)群,那么記錄將有效地被均衡到每個消費(fèi)者實(shí)例。
如果所有的消費(fèi)者實(shí)例有不同的消費(fèi)群,那么每個消息將被廣播到所有的消費(fèi)者進(jìn)程。
這是 kafka 用來實(shí)現(xiàn)一個 topic 消息的廣播(發(fā)給所有的 consumer) 和單播(發(fā)給任意一個 consumer)的手段。一個 topic 可以有多個 CG。topic 的消息會復(fù)制 (不是真的復(fù)制,是概念上的)到所有的 CG,但每個 partion 只會把消息發(fā)給該 CG 中的一 個 consumer。如果需要實(shí)現(xiàn)廣播,只要每個 consumer 有一個獨(dú)立的 CG 就可以了。要實(shí)現(xiàn)單播只要所有的 consumer 在同一個 CG。用 CG 還可以將 consumer 進(jìn)行自由的分組而不需要多次發(fā)送消息到不同的 topic;
舉個栗子:
如上圖所示,一個兩個節(jié)點(diǎn)的 Kafka 集群上擁有一個四個 partition(P0-P3)的 topic。有兩個消費(fèi)者組都在消費(fèi)這個 topic 中的數(shù)據(jù),消費(fèi)者組 A 有兩個消費(fèi)者實(shí)例,消費(fèi)者組 B 有四個消費(fèi)者實(shí)例。
從圖中我們可以看到,在同一個消費(fèi)者組中,每個消費(fèi)者實(shí)例可以消費(fèi)多個分區(qū),但是每個分區(qū)最多只能被消費(fèi)者組中的一個實(shí)例消費(fèi)。也就是說,如果有一個 4 個分區(qū)的主題,那么消費(fèi)者組中最多只能有 4 個消費(fèi)者實(shí)例去消費(fèi),多出來的都不會被分配到分區(qū)。其實(shí)這也很好理解,如果允許兩個消費(fèi)者實(shí)例同時消費(fèi)同一個分區(qū),那么就無法記錄這個分區(qū)被這個消費(fèi)者組消費(fèi)的 offset 了。如果在消費(fèi)者組中動態(tài)的上線或下線消費(fèi)者,那么 Kafka 集群會自動調(diào)整分區(qū)與消費(fèi)者實(shí)例間的對應(yīng)關(guān)系。
Kafka消費(fèi)群的實(shí)現(xiàn)方式是通過分割日志的分區(qū),分給每個 Consumer 實(shí)例,使每個實(shí)例在任何時間點(diǎn)的都可以“公平分享”獨(dú)占的分區(qū)。維持消費(fèi)群中的成員關(guān)系的這個過程是通過 Kafka 動態(tài)協(xié)議處理。如果新的實(shí)例加入該組,他將接管該組的其他成員的一些分區(qū);如果一個實(shí)例死亡,其分區(qū)將被分配到剩余的實(shí)例。
Kafka 只保證一個分區(qū)內(nèi)的消息有序,不能保證一個主題的不同分區(qū)之間的消息有序。分區(qū)的消息有序與依靠主鍵進(jìn)行數(shù)據(jù)分區(qū)的能力相結(jié)合足以滿足大多數(shù)應(yīng)用的要求。但是,如果你想要保證所有的消息都絕對有序可以只為一個主題分配一個分區(qū),雖然這將意味著每個消費(fèi)群同時只能有一個消費(fèi)進(jìn)程在消費(fèi)。
保證
Kafka 提供了以下一些高級別的保證:
由生產(chǎn)者發(fā)送到一個特定的主題分區(qū)的消息將被以他們被發(fā)送的順序來追加。也就是說,如果一個消息 M1 和消息 M2 都來自同一個生產(chǎn)者,M1 先發(fā),那么 M1 將有一個低于 M2 的偏移,會更早在日志中出現(xiàn)。
消費(fèi)者看到的記錄排序就是記錄被存儲在日志中的順序。
對于副本因子 N 的主題,我們將承受最多 N-1 次服務(wù)器故障切換而不會損失任何的已經(jīng)保存的記錄。
2.3 Kafka的使用場景
消息
Kafka 被當(dāng)作傳統(tǒng)消息中間件的替代品。消息中間件的使用原因有多種(從數(shù)據(jù)生產(chǎn)者解耦處理,緩存未處理的消息等)。與大多數(shù)消息系統(tǒng)相比,Kafka 具有更好的吞吐量,內(nèi)置的分區(qū),多副本和容錯功能,這使其成為大規(guī)模消息處理應(yīng)用程序的良好解決方案。
網(wǎng)站行為跟蹤
Kafka 的初衷就是能夠?qū)⒂脩粜袨楦櫣艿乐貥?gòu)為一組實(shí)時發(fā)布-訂閱數(shù)據(jù)源。這意味著網(wǎng)站活動(頁面瀏覽量,搜索或其他用戶行為)將被發(fā)布到中心主題,這些中心主題是每個用戶行為類型對應(yīng)一個主題的。這些數(shù)據(jù)源可被訂閱者獲取并用于一系列的場景,包括實(shí)時處理,實(shí)時監(jiān)控和加載到 Hadoop 或離線數(shù)據(jù)倉庫系統(tǒng)中進(jìn)行離線處理和報(bào)告。用戶行為跟蹤通常會產(chǎn)生巨大的數(shù)據(jù)量,因?yàn)橛脩裘總€頁面的瀏覽都會生成許多行為活動消息。
測量
Kafka 通常用于監(jiān)測數(shù)據(jù)的處理。這涉及從分布式應(yīng)用程序聚集統(tǒng)計(jì)數(shù)據(jù),生產(chǎn)出集中的運(yùn)行數(shù)據(jù)源 feeds(以便訂閱)。
日志聚合
許多人用 Kafka 作為日志聚合解決方案的替代品。日志聚合通常從服務(wù)器收集物理日志文件,并將它們集中放置(可能是文件服務(wù)器或HDFS),以便后續(xù)處理。kafka 抽象出文件的細(xì)節(jié),并將日志或事件數(shù)據(jù)作為消息流清晰地抽象出來。這為低時延的處理提供支持,而且更容易支持多個數(shù)據(jù)源和分布式的數(shù)據(jù)消費(fèi)。相比集中式的日志處理系統(tǒng)(如 Scribe 或 Flume),Kafka 性能同樣出色,而且因?yàn)楦北緜浞萏峁┝烁鼜?qiáng)的可靠性保證和更低的端到端延遲。
流處理
Kafka 的流數(shù)據(jù)管道在處理數(shù)據(jù)的時候包含多個階段,其中原始輸入數(shù)據(jù)從 Kafka 主題被消費(fèi)然后匯總,加工,或轉(zhuǎn)化成新主題用于進(jìn)一步的消費(fèi)或后續(xù)處理。例如,用于推薦新聞文章的數(shù)據(jù)流處理管道可能從 RSS 源抓取文章內(nèi)容,并將其發(fā)布到“文章”主題; 進(jìn)一步的處理可能是標(biāo)準(zhǔn)化或刪除重復(fù)數(shù)據(jù),然后發(fā)布處理過的文章內(nèi)容到一個新的主題, 最后的處理階段可能會嘗試推薦這個內(nèi)容給用戶。這種處理管道根據(jù)各個主題創(chuàng)建實(shí)時數(shù)據(jù)流圖。從版本 0.10.0.0 開始,Apache Kafka 加入了輕量級的但功能強(qiáng)大的流處理庫Kafka Streams,Kafka Streams 支持如上所述的數(shù)據(jù)處理。除了Kafka Streams,可以選擇的開源流處理工具包括Apache Storm and Apache Samza。
事件源
事件源是一種應(yīng)用程序設(shè)計(jì)風(fēng)格,是按照時間順序記錄的狀態(tài)變化的序列。Kafka 的非常強(qiáng)大的存儲日志數(shù)據(jù)的能力使它成為構(gòu)建這種應(yīng)用程序的極好的后端選擇。
提交日志
Kafka 可以為分布式系統(tǒng)提供一種外部提交日志(commit-log)服務(wù)。日志有助于節(jié)點(diǎn)之間復(fù)制數(shù)據(jù),并作為一種數(shù)據(jù)重新同步機(jī)制用來恢復(fù)故障節(jié)點(diǎn)的數(shù)據(jù)。Kafka 的 log compaction 功能有助于支持這種用法。Kafka 在這種用法中類似于 Apache BookKeeper 項(xiàng)目。
-
大數(shù)據(jù)
+關(guān)注
關(guān)注
64文章
8960瀏覽量
140181 -
消息隊(duì)列
+關(guān)注
關(guān)注
0文章
34瀏覽量
3133 -
kafka
+關(guān)注
關(guān)注
0文章
54瀏覽量
5400
原文標(biāo)題:程序員必須了解的消息隊(duì)列之王-Kafka
文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
評論