簡介
Apache Kafka由著名職業社交公司LinkedIn開發,最初是被設計用來解決LinkedIn公司內部海量日志傳輸等問題。Kafka使用Scala語言編寫,于2011年開源并進入Apache孵化器,2012年10月正式畢業,現在為Apache頂級項目。本文旨在使讀者對Kafka有一個較為基本和全面的認識。
基本概念
Kafka是一個分布式數據流平臺,可以運行在單臺服務器上,也可以在多臺服務器上部署形成集群。它提供了發布和訂閱功能,使用者可以發送數據到Kafka中,也可以從Kafka中讀取數據(以便進行后續的處理)。Kafka具有高吞吐、低延遲、高容錯等特點。下面介紹一下Kafka中常用的基本概念:
- Broker
消息隊列中常用的概念,在Kafka中指部署了Kafka實例的服務器節點。 - Topic
用來區分不同類型信息的主題。比如應用程序A訂閱了主題t1,應用程序B訂閱了主題t2而沒有訂閱t1,那么發送到主題t1中的數據將只能被應用程序A讀到,而不會被應用程序B讀到。 - Partition
每個topic可以有一個或多個partition(分區)。分區是在物理層面上的,不同的分區對應著不同的數據文件。Kafka使用分區支持物理上的并發寫入和讀取,從而大大提高了吞吐量。 - Record
實際寫入Kafka中并可以被讀取的消息記錄。每個record包含了key、value和timestamp。 - Producer
生產者,用來向Kafka中發送數據(record)。 - Consumer
消費者,用來讀取Kafka中的數據(record)。 - Consumer Group
一個消費者組可以包含一個或多個消費者。使用多分區+多消費者方式可以極大提高數據下游的處理速度。
基本原理
Topic和數據日志
主題是同一類別的消息記錄(record)的集合。在Kafka中,一個主題通常有多個訂閱者。對于每個主題,Kafka集群維護了一個分區數據日志文件結構如下:
每個partition都是一個有序并且不可變的消息記錄集合。當新的數據寫入時,就被追加到partition的末尾。在每個partition中,每條消息都會被分配一個順序的唯一標識,這個標識被稱為offset,即偏移量。注意,Kafka只保證在同一個partition內部消息是有序的,在不同partition之間,并不能保證消息有序。
Kafka可以配置一個保留期限,用來標識日志會在Kafka集群內保留多長時間。Kafka集群會保留在保留期限內所有被發布的消息,不管這些消息是否被消費過。比如保留期限設置為兩天,那么數據被發布到Kafka集群的兩天以內,所有的這些數據都可以被消費。當超過兩天,這些數據將會被清空,以便為后續的數據騰出空間。由于Kafka會將數據進行持久化存儲(即寫入到硬盤上),所以保留的數據大小可以設置為一個比較大的值。
事實上,在單個消費者層面上,每個消費者保存的唯一的元數據就是它所消費的數據日志文件的偏移量。偏移量是由消費者來控制的,通常情況下,消費者會在讀取記錄時線性的提高其偏移量。不過由于偏移量是由消費者控制,所以消費者可以將偏移量設置到任何位置,比如設置到以前的位置對數據進行重復消費,或者設置到最新位置來跳過一些數據。
容錯
每個topic的分區都可以分布在Kafka集群的不同服務器上。比如topic A有partition 0,1,2,分別分布在Broker 1,2,3上面。每個服務器都可以處理分布在它上面的分區的寫入和讀取操作。另外,每個分區也可以配置多個副本用來提高容錯性。
每個partition有一個服務器充當“leader”,零至多個服務器充當“follower”。Leader會處理針對于這個分區的所有讀寫操作,而follower只是被動的從leader中復制數據。當leader掛掉了,那么原有的follower會自動選舉出一個新的leader。每臺服務器都會作為一些分區的leader,也會作為其他分區的follower,所以Kafka集群內的負載會比較均衡。
生產者
生產者可以將數據寫入到選定的主題。生產者負責決定要將哪條記錄寫入到那個分區當中。可以使用輪詢方式,即每次取一小段時間的數據寫入某個partition,下一小段的時間寫入下一個partition;也可以使用一些分區函數(比如哈希),根據record的key值將記錄寫入不同的分區。
消費者
多個消費者實例可以組成一個消費者組,并用一個標簽來標識這個消費者組。一個消費者組中的不同消費者實例可以運行在不同的進程甚至不同的服務器上。
如果所有的消費者實例都在同一個消費者組中,那么消息記錄會被很好的均衡的發送到每個消費者實例。
如果所有的消費者實例都在不同的消費者組,那么每一條消息記錄會被廣播到每一個消費者實例。
舉個例子。如上圖所示,一個兩個節點的Kafka集群上擁有一個四個partition(P0-P3)的topic。有兩個消費者組都在消費這個topic中的數據,消費者組A有兩個消費者實例,消費者組B有四個消費者實例。
從圖中我們可以看到,在同一個消費者組中,每個消費者實例可以消費多個分區,但是每個分區最多只能被消費者組中的一個實例消費。也就是說,如果有一個4個分區的主題,那么消費者組中最多只能有4個消費者實例去消費,多出來的都不會被分配到分區。其實這也很好理解,如果允許兩個消費者實例同時消費同一個分區,那么就無法記錄這個分區被這個消費者組消費的offset了。如果在消費者組中動態的上線或下線消費者,那么Kafka集群會自動調整分區與消費者實例間的對應關系。
使用場景
上面介紹了Kafka的一些基本概念和原理,那么Kafka可以做什么呢?目前主流使用場景基本如下:
消息隊列(MQ)
在系統架構設計中,經常會使用消息隊列(Message Queue)——MQ。MQ是一種跨進程的通信機制,用于上下游的消息傳遞,使用MQ可以使上下游解耦,消息發送上游只需要依賴MQ,邏輯上和物理上都不需要依賴其他下游服務。MQ的常見使用場景如流量削峰、數據驅動的任務依賴等等。在MQ領域,除了Kafka外還有傳統的消息隊列如ActiveMQ和RabbitMQ等。
追蹤網站活動
Kafka最出就是被設計用來進行網站活動(比如PV、UV、搜索記錄等)的追蹤。可以將不同的活動放入不同的主題,供后續的實時計算、實時監控等程序使用,也可以將數據導入到數據倉庫中進行后續的離線處理和生成報表等。
Metrics
Kafka經常被用來傳輸監控數據。主要用來聚合分布式應用程序的統計數據,將數據集中后進行統一的分析和展示等。
日志聚合
很多人使用Kafka作為日志聚合的解決方案。日志聚合通常指將不同服務器上的日志收集起來并放入一個日志中心,比如一臺文件服務器或者HDFS中的一個目錄,供后續進行分析處理。相比于Flume和Scribe等日志聚合工具,Kafka具有更出色的性能。