【Apache Kafka】一、Kafka簡介及其基本原理


  對於大數據,我們要考慮的問題有很多,首先海量數據如何收集(如Flume),然后對於收集到的數據如何存儲(典型的分布式文件系統HDFS、分布式數據庫HBase、NoSQL數據庫Redis),其次存儲的數據不是存起來就沒事了,要通過計算從中獲取有用的信息,這就涉及到計算模型(典型的離線計算MapReduce、流式實時計算Storm、Spark),或者要從數據中挖掘信息,還需要相應的機器學習算法。在這些之上,還有一些各種各樣的查詢分析數據的工具(如Hive、Pig等)。除此之外,要構建分布式應用還需要一些工具,比如分布式協調服務Zookeeper等等。

  這里,我們講到的是消息系統,Kafka專為分布式高吞吐量系統而設計,其他消息傳遞系統相比,Kafka具有更好的吞吐量,內置分區,復制和固有的容錯能力,這使得它非常適合大規模消息處理應用程序。

(一)消息系統

  首先,我們理解一下什么是消息系統:消息系統負責將數據從一個應用程序傳輸到另外一個應用程序,使得應用程序可以專注於處理邏輯,而不用過多的考慮如何將消息共享出去。

  分布式消息系統基於可靠消息隊列的方式,消息在應用程序和消息系統之間異步排隊。實際上,消息系統有兩種消息傳遞模式:一種是點對點,另外一種是基於發布-訂閱(publish-subscribe)的消息系統。

1、點對點的消息系統

  在點對點的消息系統中,消息保留在隊列中,一個或者多個消費者可以消耗隊列中的消息,但是消息最多只能被一個消費者消費,一旦有一個消費者將其消費掉,消息就從該隊列中消失。這里要注意:多個消費者可以同時工作,但是最終能拿到該消息的只有其中一個。最典型的例子就是訂單處理系統,多個訂單處理器可以同時工作,但是對於一個特定的訂單,只有其中一個訂單處理器可以拿到該訂單進行處理。

2、發布-訂閱消息系統

  在發布 - 訂閱系統中,消息被保留在主題中。 與點對點系統不同,消費者可以訂閱一個或多個主題並使用該主題中的所有消息。在發布 - 訂閱系統中,消息生產者稱為發布者,消息使用者稱為訂閱者。 一個現實生活的例子是Dish電視,它發布不同的渠道,如運動,電影,音樂等,任何人都可以訂閱自己的頻道集,並獲得他們訂閱的頻道時可用。

(二)Apache Kafka簡介

  Kafka is a distributed,partitioned,replicated commit logservice。

  Apache Kafka是一個分布式發布 - 訂閱消息系統和一個強大的隊列,可以處理大量的數據,並使你能夠將消息從一個端點傳遞到另一個端點。 Kafka適合離線和在線消息消費。 Kafka消息保留在磁盤上,並在群集內復制以防止數據丟失。 Kafka構建在ZooKeeper同步服務之上。 它與Apache Storm和Spark非常好地集成,用於實時流式數據分析。

  Kafka 是一個分布式消息隊列,具有高性能、持久化、多副本備份、橫向擴展能力。生產者往隊列里寫消息,消費者從隊列里取消息進行業務邏輯。一般在架構設計中起到解耦、削峰、異步處理的作用。

  關鍵術語:

  (1)生產者和消費者(producer和consumer):消息的發送者叫Producer,消息的使用者和接受者是Consumer,生產者將數據保存到Kafka集群中,消費者從中獲取消息進行業務的處理。

  (2)broker:Kafka集群中有很多台Server,其中每一台Server都可以存儲消息,將每一台Server稱為一個kafka實例,也叫做broker。

  (3)主題(topic):一個topic里保存的是同一類消息,相當於對消息的分類,每個producer將消息發送到kafka中,都需要指明要存的topic是哪個,也就是指明這個消息屬於哪一類。

  (4)分區(partition):每個topic都可以分成多個partition,每個partition在存儲層面是append log文件。任何發布到此partition的消息都會被直接追加到log文件的尾部。為什么要進行分區呢?最根本的原因就是:kafka基於文件進行存儲,當文件內容大到一定程度時,很容易達到單個磁盤的上限,因此,采用分區的辦法,一個分區對應一個文件,這樣就可以將數據分別存儲到不同的server上去,另外這樣做也可以負載均衡,容納更多的消費者。

  (5)偏移量(Offset):一個分區對應一個磁盤上的文件,而消息在文件中的位置就稱為offset(偏移量),offset為一個long型數字,它可以唯一標記一條消息。由於kafka並沒有提供其他額外的索引機制來存儲offset,文件只能順序的讀寫,所以在kafka中幾乎不允許對消息進行“隨機讀寫”。

  綜上,我們總結一下Kafka的幾個要點:

  • kafka是一個基於發布-訂閱的分布式消息系統(消息隊列)
  • Kafka面向大數據,消息保存在主題中,而每個topic有分為多個分區
  • kafak的消息數據保存在磁盤,每個partition對應磁盤上的一個文件,消息寫入就是簡單的文件追加,文件可以在集群內復制備份以防丟失
  • 即使消息被消費,kafka也不會立即刪除該消息,可以通過配置使得過一段時間后自動刪除以釋放磁盤空間
  • kafka依賴分布式協調服務Zookeeper,適合離線/在線信息的消費,與storm和saprk等實時流式數據分析常常結合使用

(三)Apache Kafka基本原理

  通過之前的介紹,我們對kafka有了一個簡單的理解,它的設計初衷是建立一個統一的信息收集平台,使其可以做到對信息的實時反饋。Kafka is a distributed,partitioned,replicated commit logservice。接下來我們着重從幾個方面分析其基本原理。

1、分布式和分區(distributed、partitioned)

  我們說kafka是一個分布式消息系統,所謂的分布式,實際上我們已經大致了解。消息保存在Topic中,而為了能夠實現大數據的存儲,一個topic划分為多個分區,每個分區對應一個文件,可以分別存儲到不同的機器上,以實現分布式的集群存儲。另外,每個partition可以有一定的副本,備份到多台機器上,以提高可用性。

  總結起來就是:一個topic對應的多個partition分散存儲到集群中的多個broker上,存儲方式是一個partition對應一個文件,每個broker負責存儲在自己機器上的partition中的消息讀寫。

2、副本(replicated )

  kafka還可以配置partitions需要備份的個數(replicas),每個partition將會被備份到多台機器上,以提高可用性,備份的數量可以通過配置文件指定。

  這種冗余備份的方式在分布式系統中是很常見的,那么既然有副本,就涉及到對同一個文件的多個備份如何進行管理和調度。kafka采取的方案是:每個partition選舉一個server作為“leader”,由leader負責所有對該分區的讀寫,其他server作為follower只需要簡單的與leader同步,保持跟進即可。如果原來的leader失效,會重新選舉由其他的follower來成為新的leader。

  至於如何選取leader,實際上如果我們了解ZooKeeper,就會發現其實這正是Zookeeper所擅長的,Kafka 使用 ZK 在 Broker 中選出一個 Controller,用於 Partition 分配和 Leader 選舉。

  另外,這里我們可以看到,實際上作為leader的server承擔了該分區所有的讀寫請求,因此其壓力是比較大的,從整體考慮,從多少個partition就意味着會有多少個leader,kafka會將leader分散到不同的broker上,確保整體的負載均衡。

3、整體數據流程

  Kafka 的總體數據流滿足下圖,該圖可以說是概括了整個kafka的基本原理。


(1)數據生產過程(Produce)

  對於生產者要寫入的一條記錄,可以指定四個參數:分別是topic、partition、key和value,其中topic和value(要寫入的數據)是必須要指定的,而key和partition是可選的。

  對於一條記錄,先對其進行序列化,然后按照 Topic 和 Partition,放進對應的發送隊列中。如果 Partition 沒填,那么情況會是這樣的:a、Key 有填。按照 Key 進行哈希,相同 Key 去一個 Partition。b、Key 沒填。Round-Robin 來選 Partition。

  producer將會和Topic下所有partition leader保持socket連接,消息由producer直接通過socket發送到broker。其中partition leader的位置(host:port)注冊在zookeeper中,producer作為zookeeper client,已經注冊了watch用來監聽partition leader的變更事件,因此,可以准確的知道誰是當前的leader。

  producer端采用異步發送:將多條消息暫且在客戶端buffer起來,並將他們批量的發送到broker,小數據IO太多,會拖慢整體的網絡延遲,批量延遲發送事實上提升了網絡效率。

(2)數據消費過程(Consume)

  對於消費者,不是以單獨的形式存在的,每一個消費者屬於一個consumer group,一個group包含多個consumer。特別需要注意的是:訂閱Topic是以一個消費組來訂閱的,發送到Topic的消息,只會被訂閱此Topic的每個group中的一個consumer消費

  如果所有的Consumer都具有相同的group,那么就像是一個點對點的消息系統;如果每個consumer都具有不同的group,那么消息會廣播給所有的消費者。

  具體說來,這實際上市根據partition來分的,一個 Partition,只能被消費組里的一個消費者消費,但是可以同時被多個消費組消費,消費組里的每個消費者是關聯到一個partition的,因此有這樣的說法:對於一個topic,同一個group中不能有多於partitions個數的consumer同時消費,否則將意味着某些consumer將無法得到消息。

  同一個消費組的兩個消費者不會同時消費一個partition。

  在kafka中,采用了pull方式,即consumer在和broker建立連接之后,主動去pull(或者說fetch)消息,首先consumer端可以根據自己的消費能力適時的去fetch消息並處理,且可以控制消息消費的進度(offset)。

  partition中的消息只有一個consumer在消費,且不存在消息狀態的控制,也沒有復雜的消息確認機制,可見kafka broker端是相當輕量級的。當消息被consumer接收之后,需要保存 Offset 記錄消費到哪,以前保存在 ZK 中,由於 ZK 的寫性能不好,以前的解決方法都是 Consumer 每隔一分鍾上報一次,在 0.10 版本后,Kafka 把這個 Offset 的保存,從 ZK 中剝離,保存在一個名叫 consumeroffsets topic 的 Topic 中,由此可見,consumer客戶端也很輕量級。

4、消息傳送機制

  Kafka 支持 3 種消息投遞語義,在業務中,常常都是使用 At least once 的模型。

  • At most once:最多一次,消息可能會丟失,但不會重復。
  • At least once:最少一次,消息不會丟失,可能會重復。
  • Exactly once:只且一次,消息不丟失不重復,只且消費一次。

參考鏈接:

注:本文是一個總結性筆記,參考了一些其他寫的不錯的文章,特在此進行說明,主要如下:

https://www.cnblogs.com/cxhfuujust/p/10941674.html

https://www.w3cschool.cn/apache_kafka/apache_kafka_introduction.html

https://www.cnblogs.com/likehua/p/3999538.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM