1. 程式人生 > >[Kafka][1][初識Kafka]

[Kafka][1][初識Kafka]

[TOC] ## 第1章 初識Kafka >參考資料 > >- [Kafka權威指南](https://book.douban.com/subject/27665114/) 資料為企業的發展提供動力。我們從資料中獲取資訊,對它們進行分析處理,然後生成更多的資料。每個應用程式都會產生資料,包括日誌訊息、度量指標、使用者活動記錄、響應訊息等。資料的點點滴滴都在暗示一些重要的事情,比如下一步行動的方向。 ### 1.1 釋出與訂閱訊息系統 先來了解發布與訂閱訊息系統的概念,並認識這個系統的重要性。 - 資料(訊息)的**傳送者**(釋出者)**不會直接**把訊息傳送給**接收者**,這是釋出與訂閱訊息系統的一個特點。 - 釋出者以某種方式**對訊息進行分類**,接收(訂閱者)**訂閱**它們,以便接收特定型別的訊息。 - 釋出與訂閱系統一般會有一個**broker**,也就是釋出訊息的中心點。 #### 1.1.1 如何開始 釋出與訂閱訊息系統的大部分**應用場景**都是從一個**簡單**的**程序間通道**開始的。例如,你的應用需要往別處**傳送度量指標(metric)**,可以在你的**應用**和另一個可以在**儀表盤應用**之間建立**直接連線**,然後通過這個連線推送度量指標,如下圖所示。 ![](https://healthlung.oss-cn-beijing.aliyuncs.com/20201122152443.png) 但是這種方式在應對**複雜場景**時並不適合,如下圖,如果場景變得複雜,**直連**會**讓節點間的通訊變得一團糟** ![](https://healthlung.oss-cn-beijing.aliyuncs.com/20201122152645.png) 這時,技術債務開始凸顯出來,於是你決定償還掉一些。 - 你建立了一個**獨立的應用**:用於**接收**來自其他應用程式的**度量指標**,併為其他應用提供一個**查詢服務**。這樣,之前架構的複雜度被降低到圖1-3 所示的那樣。 - 那麼恭喜你,你已經建立了一個**基於釋出與訂閱**的**訊息系統**。 ![](https://healthlung.oss-cn-beijing.aliyuncs.com/20201122152906.png) #### 1.1.2 獨立的佇列系統 在你跟**度量指標**打得不可開交的時候,你的一個同事也正在跟**日誌**訊息奮戰。還有另一個同事正在**跟蹤網站使用者的行為**,為負責機器學習開發的同事提供資訊,同時為管理團隊生成報告。你和同事們使用**相同的方式建立這些系統**,解耦資訊的釋出者和訂閱者。 圖1-4所示的架構包含了**3 個獨立的** **釋出與訂閱系統**。 - **指標**(Metric)的釋出訂閱系統 - **日誌**(logging)的釋出訂閱系統 - **使用者跟蹤**(tracking)的釋出訂閱系統 ![](https://healthlung.oss-cn-beijing.aliyuncs.com/20201122153146.png) 此時,你真正需要的是一個**單一**的**集中式系統**,它可以用來**釋出和訂閱** **多種通用型別的資料**,其規模可以隨著公司業務的增長而增長。 ### 1.2 Kafka登場 Kafka 就是為了**解決上述問題**而設計的一款**基於釋出與訂閱的訊息系統**。 - 它一般被稱為“**分散式提交日誌**”或者“**分散式流平臺**”。 - Kafka 中的資料是按照一定**順序** **持久化**儲存的,可以按需讀取。 - 並且Kafka 的**資料** **分佈在Kafka叢集的各個部分**,具備資料**故障保護**和**效能伸縮**能力。 #### 1.2.1 訊息和批次(Message and batch) Kafka 的**資料單元**被稱為**訊息**。 - 訊息由**位元組陣列**組成。 - 訊息可以有一個**鍵**,鍵也是一個位元組陣列。可以**通過鍵**,**控制訊息寫入哪個分割槽**。最簡單的例子就是為鍵生成一個雜湊值,然後使用雜湊值對主題分割槽數進行取模,為訊息選取分割槽。這樣可以保證具有相同鍵的訊息總是被寫到相同的分割槽上。 為了提高效率,訊息被分**批次**寫入Kafka。 - 批次就是**一組訊息**,這些訊息屬於**同一個主題的同一分割槽**。 - 如果每一個訊息都單獨穿行於網路,會導致大量的網路開銷,把訊息分成批次傳輸可以**減少網路開銷**。 #### 1.2.2 模式(schema) 對於Kafka 來說,訊息不過是晦澀難懂的位元組陣列,所以有人建議用一些**額外的結構**來**定義訊息內容含義**,讓它們更易於理解,這就是**模式**。 Kafka 的開發者一般使用**Apache Avro**來**定義模式** - 它最初是為Hadoop 開發的一款**序列化框架**。 - Avro 提供了一種緊湊的序列化格式,**模式**和**訊息體**是**分開**的; - 它還支援**強型別**和**模式進化**,其**版本**既向前**相容**,也向後相容。 #### 1.2.3 主題和分割槽(Topic and Partition) Kafka 的訊息通過**主題**進行分類。 - 主題就好比資料庫的**表**,或者檔案系統裡的**資料夾**。 - **主題**可以被分為若干個**分割槽**,一個分割槽就是一個**提交日誌(commit log)**。 - 訊息以**追加**的方式寫入分割槽,然後以**先入先出(FIFO)**的順序**讀取**。 - 要注意,由於一個主題一般包含幾個分割槽,因此**無法在整個主題範圍內**保證訊息**有序**,但可以保證訊息在**單個分割槽內** **有序**。 - Kafka 通過**分割槽**來實現**資料冗餘(redundency)**和**伸縮性(scalability)**。 - 分割槽可以分佈在不同的伺服器上,也就是說,一個**主題**可以**橫跨多個伺服器**,以此來提供比單個伺服器更強大的效能。 圖1-5 所示的主題有4個分割槽,訊息被追加寫入每個分割槽的尾部。 ![](https://healthlung.oss-cn-beijing.aliyuncs.com/20201122155245.png) #### 1.2.4 生產者和消費者 Kafka 系統的**使用者**被分為**兩種**:**生產者**和**消費者** **生產者建立訊息**。 - 一般情況下,一個訊息會被髮布到一個特定的**主題**上。 - 生產者在預設情況下把訊息**均衡**地分佈到**主題的所有分割槽**上,而並不關心特定訊息會被寫到哪個分割槽。 - 不過,在**某些情況下**,生產者也可以通過**分割槽器**和**鍵**,把訊息直接**寫到指定的分割槽**。 **消費者讀取訊息**。 - 消費者**訂閱**一個或多個**主題**,並按照訊息生成的**順序讀取**它們。 - 消費者通過檢查訊息的**偏移量**來區分已經讀取過的訊息。 - 偏移量是**訊息的一種元資料**,它是一個不斷**遞增**的整數值,在建立每條訊息時,Kafka 會把它附加到每條訊息裡。 - 消費者把每個分割槽**最後讀取的訊息**的**偏移量** **儲存**在Zookeeper 或Kafka 上,如果消費者關閉或重啟,它的**讀取狀態不會丟失**。 可以將多個消費者組織成一個**消費者群組**,來**共享**一個主題: - **同一群組**的多個消費者共同**讀取一個主題**。 - 群組保證**每個分割槽**只能被**一個消費者**使用,並且整個群組對於**主題中的每條訊息**精確**處理一次**。 - 消費者與分割槽之間的**對映**通常被稱為消費者對分割槽的**所有權關係**。 圖1-6 所示的群組中,有3 個消費者同時讀取一個主題。其中的兩個消費者各自讀取一個分割槽,另外一個消費者讀取其他兩個分割槽。 ![](https://healthlung.oss-cn-beijing.aliyuncs.com/20201122161046.png) #### 1.2.5 broker和叢集 一個獨立的Kafka 伺服器被稱為**broker**。 - broker **接收**來自**生產者**的訊息,為訊息設定偏移量,並提交訊息到**磁碟儲存**。 - broker 為**消費者**提供服務,對讀取分割槽的請求作出**響應**,返回已經提交到磁碟上的訊息。 多個broker可以組成一個Kafka**叢集** - 每個叢集都有一個broker 同時充當了**叢集控制器**的角色。控制器負責管理叢集,包括將**分割槽分配**給broker 和**監控**broker。 - 在叢集中,**每個分割槽**都對應一個**首領broker**,該broker 被稱為分割槽的首領。 - 並且**一個分割槽**可以分配給**多個broker**,但只有一個首領。其他broker都是這個首領的**從者broker**。這個時候會發生**分割槽複製**。首領broker會複製訊息到從者broker。這種複製機制為分割槽提供了**訊息冗餘** - 這樣,如果**首領broker 失效**,從者broker可以**接管**領導權,而服務不會停止且訊息不會丟失 ![](https://healthlung.oss-cn-beijing.aliyuncs.com/20201122161736.png) **保留訊息**(在一定期限內)是Kafka 的一個重要特性。Kafka broker 預設的訊息保留策略是這樣的: - 要麼保留一段時間(比如7 天), - 要麼保留到訊息達到一定大小的位元組數(比如1GB)。 #### 1.2.6 多叢集 kafka也支援**多叢集**。如下圖 ![](https://healthlung.oss-cn-beijing.aliyuncs.com/20201122161957.png) 多叢集具體介紹略,後面章節會提到。 ### 1.3 為什麼選擇Kafka 有很多其他的釋出/訂閱訊息傳遞系統,例如:RabbitMQ、ActiveMQ等,那麼是什麼讓Apache Kafka成為一個好的選擇呢? #### 1.3.1 多個生產者 卡夫卡能夠無縫地支援**多個生產者**,無論這些生產者使用的是多個主題還是同一主題。這使得該系統非常適合**聚合**來自許多前端系統的資料,並使其保持一致。 #### 1.3.2 多個消費者 Kafka 也支援**多個消費者**從**同一個訊息流**上讀取資料,而且消費者之間**互不影響**。這與其他佇列系統不同,其他佇列系統的訊息一旦被一個客戶端讀取,其他客戶端就無法再讀取它。 另外,多個消費者可以組成一個**消費者群組**,它們**共享**一個訊息流,並保證**整個群組**對**每條訊息**只處理**一次**。 #### 1.3.3 基於磁碟的資料儲存 Kafka允許**消費者** **非實時**地讀取訊息,這要歸功於Kafka 的**訊息保留**特性。 - 消費者可能會因為**自身處理能力低**或突發的**流量高峰**導致**無法及時**讀取訊息 - 而**持久化資料**可以**保證資料不會丟失**。 - 消費者可以在進行應用程式維護時離線一小段時間,而無需擔心訊息丟失或堵塞在生產者端。 - 消費者可以被關閉,但訊息會繼續保留在Kafka 裡。消費者可以從上次中斷的地方繼續處理訊息。 #### 1.3.4 伸縮性 Kafka可以通過**增加broker**的方式來實現**橫向擴充套件**,它的**伸縮性**很靈活 >例如:使用者在開發階段可以先使用單個broker,再擴充套件到包含3 個broker 的小型開發叢集,然後隨著資料量不斷增長,部署到生產環境的叢集可能包含上百個broker。 #### 1.3.5 高效能 上面提到的所有特性,讓Kafka 成為了一個高效能的釋出與訂閱訊息系統。通過橫向擴充套件生產者、消費者和broker,Kafka 可以輕鬆處理巨大的訊息流。在處理大量資料的同時,它還能保證**亞秒級的訊息延遲**。 ### 1.4 Kafka在資料生態系統中的重要性 在現代應用場景中,資料分佈在很多不同的應用。這些應用可以整體上看作一個數據生態系統。 Kafka 為資料生態系統帶來了**迴圈系統**,如圖1-9 所示。 - 它負責各個應用間的**訊息傳遞**,為所有應用提供**一致的介面**。 - 生產者應用和消費者應用之間不再有緊密的**耦合**,也不需要在它們之間建立任何型別的**直連**。 - 我們可以根據業務需要**新增或移除應用**,因為生產者不再關心誰在使用資料,也不關心有多少個消費者。 ![](https://healthlung.oss-cn-beijing.aliyuncs.com/20201122163514.png) ### 1.5 使用場景 #### 1.5.1 活動跟蹤(Activity tracking) Kafka 最初的使用場景是**跟蹤使用者的活動**。 - 網站使用者與前端應用程式發生互動,前端應用程式生成**使用者活動相關的訊息**。這些訊息比如頁面訪問次數和點選量。 - 這些訊息可以被**釋出到Kafka**的一個或多個主題上,然後由一個或多個**後端應用程式負責讀取**。這樣,我們就可以用它們來**生成報告**,為**機器學習**系統提供資料,**更新搜尋結果**等等。 #### 1.5.2 傳送通知(Messaging) Kafka 的另一個基本用途是**傳送通知**。 - **應用程式向用戶傳送通知**(比如**郵件**)就是通過傳遞訊息來實現的。 - 這些應用程式元件可以**直接**生成訊息並**釋出到kafka**,而不需要關心訊息是如何傳送給使用者的,也不需要關心這些訊息傳送給使用者時是什麼格式的。 - 另一個**公共應用程式**會從Kakfa**讀取**這些訊息,並且**處理**訊息成適合使用者閱讀的格式,然後**傳送**給使用者 #### 1.5.3 度量指標和日誌記錄(Metric and logging) Kafka 也可以用於收集應用程式和系統度量指標以及日誌。 - 多個不同的應用程式定期把**度量指標**釋出到Kafka 主題上,監控系統讀取並分析這些訊息。 - **日誌訊息**也可以被髮布到Kafka 主題上,然專門的日誌搜尋系統(比如Elasticsearch)或安全分析應用程式會讀取並處理它們。 #### 1.5.4 提交日誌(Commit log) **Kafka 的基本概念來源於資料庫的提交日誌**,所以使用Kafka 作為提交日誌是件順理成章的事。我們可以把資料庫的更新放到Kafka 上,應用程式可以讀取這些更新。 - 例如:資料庫主庫和從庫之間的**更新複製** - 或者**合併**多個數據庫的**更新**到一個數據庫例項上 #### 1.5.5 流處理(Streaming processing) 使用者可以編寫小型應用程式來操作Kafka 訊息,比如計算度量指標,為其他應用程式有效地處理訊息分割槽,或者對來自多個數據源的訊息進行轉換。 ### 1.6 起源故事 #### 1.6.1LinkedIn的問題 LinkedIn 有一個**指標監控系統**。LinkedIn 還有一個比較複雜的**請求跟蹤系統**。與此同時,還建立了另一個用於**收集使用者活動資訊的系統**。這些系統都需要從多個前端獲取資料,這時就需要一個**統一且通用的釋出訂閱系統**。 #### 1.6.2 Kafka的誕生 LinkedIn 的開發團隊由Jay Kreps 領導。Jay Kreps 是LinkedIn 的首席工程師,之前負責分散式鍵值儲存系統Voldemort 的開發。初建團隊成員還包括Neha Narkhede,不久之後,Jun Rao 也加入了進來。他們一起著手建立一個訊息系統,可以同時滿足上述的兩種需求,並且可以在未來進行橫向擴充套件。他們的主要目標如下: - 使用**推送和拉取**模型**解耦生產者和消費者**; - 為訊息傳遞系統中的訊息提供**資料持久化**,以便支援**多個消費者**; - 通過系統優化實現**高吞吐量**; - 系統可以隨著資料流的增長進行**橫向擴充套件**。 最後我們看到的這個釋出與訂閱訊息系統具有**典型的訊息系統介面**,但從**儲存層**來看,它**更像是一個日誌聚合系統**。Kafka 使用**Avro** 作為訊息序列化框架,每天高效地處理數十億級別的度量指標和使用者活動跟蹤資訊。LinkedIn 已經擁有超過萬億級別的訊息使用量(截止到2015 年8 月),而且每天仍然需要處理超過千萬億位元組的資料。 #### 1.6.3 走向開源 略 #### 1.6.4 命名 >我想既然Kafka 是為了寫資料而產生的,那麼用作家的名字來命名會顯得更有意義。我在大學時期上過很多文學課程,很喜歡Franz Kafka。況且,對於開源專案來說,這個名字聽起來很酷。因此,名字和應用本身基本沒有太多聯絡。-------J