閱讀446 返回首頁    go 阿裏雲 go 技術社區[雲棲]


kafka設計與原理

一、kafka的一些重要設計思想:
1. Consumergroup:各個consumer可以zuche組成一個組,每個消息隻能組中一個consumer消費,如果一個消息可以被多個consumer消費的話,那麼這些consumer必須在不同的組。
2. 消息狀態:在Kafka中,消息的狀態被保存在consumer中,broker不會關心哪個消息被消費了被誰消費了,隻記錄一個offset值(指向partition中下一個要被消費的消息位置),這就意味著如果consumer處理不好的話,broker上的一個消息可能會被消費多次。
消息持久化:Kafka中會把消息持久化到本地文件係統中。
消息有效期:Kafka會長久保留其中的消息,以便consumer可以多次消費,當然其中很多細節是可配置的
批量發送:Kafka支持以消息集合為單位進行批量發送,以提高push效率。
Kafka集群中broker之間的關係:不是主從關係,各個broker在集群中地位一樣,我們可以隨意的增加或刪除任何一個broker節點。
分區機製partition:Kafka的broker端支持消息分區,Producer可以決定把消息發到哪個分區,在一個分區中消息的順序就是Producer發送消息的順序,一個主題中可以有多個分區,具體分區的數量是可配置的。分區的意義很重大,後麵的內容會逐漸體現。
二、kafka架構組件
topic:消息存放的目錄即主題
Producer:生產消息到topic的一方
Consumer:訂閱topic消費消息的一方
Broker:Kafka的服務實例就是一個broker
三、Kafka Topic&Partition
kafka的每個topic可以設置多個partition。
image
四、kafka核心組件
1.Replications、Partitions 和Leaders
kafka中數據是持久化的,並且有容錯機製,kafka的每個topic可以設置多個副本,存入不同的broker。
Kafka中的topic是以partition的形式存放的,每一個topic都可以設置它的partition數量,Partition的數量決定了組成topic的log的數量。Producer在生產數據時,會按照一定規則(這個規則是可以自定義的)把消息發布到topic的各個partition中。上麵將的副本都是以partition為單位的,不過隻有一個partition的副本會被選舉成leader作為讀寫用。
關於如何設置partition值需要考慮的因素。一個partition隻能被一個消費者消費(一個消費者可以同時消費多個partition),因此,如果設置的partition的數量小於consumer的數量,就會有消費者消費不到數據。所以,推薦partition的數量一定要大於同時運行的consumer的數量。另外一方麵,建議partition的數量大於集群broker的數量,這樣leader partition就可以均勻的分布在各個broker中,最終使得集群負載均衡。在Cloudera,每個topic都有上百個partition。需要注意的是,kafka需要為每個partition分配一些內存來緩存消息數據,如果partition數量越大,就要為kafka分配更大的heap space。
2.Producers
Producers直接發送消息到broker上的leader partition,不需要經過任何中介一係列的路由轉發。為了實現這個特性,kafka集群中的每個broker都可以響應producer的請求,並返回topic的一些元信息,這些元信息包括哪些機器是存活的,topic的leader partition都在哪,現階段哪些leader partition是可以直接被訪問的。
Producer客戶端自己控製著消息被推送到哪些partition。實現的方式可以是隨機分配、實現一類隨機負載均衡算法,或者指定一些分區算法。Kafka提供了接口供用戶實現自定義的分區,用戶可以為每個消息指定一個partitionKey,通過這個key來實現一些hash分區算法。比如,把userid作為partitionkey的話,相同userid的消息將會被推送到同一個分區。
以Batch的方式推送數據可以極大的提高處理效率,kafka Producer 可以將消息在內存中累計到一定數量後作為一個batch發送請求。Batch的數量大小可以通過Producer的參數控製,參數值可以設置為累計的消息的數量(如500條)、累計的時間間隔(如100ms)或者累計的數據大小(64KB)。通過增加batch的大小,可以減少網絡請求和磁盤IO的次數,當然具體參數設置需要在效率和時效性方麵做一個權衡。
Producers可以異步的並行的向kafka發送消息,但是通常producer在發送完消息之後會得到一個future響應,返回的是offset值或者發送過程中遇到的錯誤。這其中有個非常重要的參數“acks”,這個參數決定了producer要求leader partition 收到確認的副本個數,如果acks設置數量為0,表示producer不會等待broker的響應,所以,producer無法知道消息是否發送成功,這樣有可能會導致數據丟失,但同時,acks值為0會得到最大的係統吞吐量。
若acks設置為1,表示producer會在leader partition收到消息時得到broker的一個確認,這樣會有更好的可靠性,因為客戶端會等待直到broker確認收到消息。若設置為-1,producer會在所有備份的partition收到消息時得到broker的確認,這個設置可以得到最高的可靠性保證。

Kafka 消息有一個定長的header和變長的字節數組組成。因為kafka消息支持字節數組,也就使得kafka可以支持任何用戶自定義的序列號格式或者其它已有的格式如Apache Avro、protobuf等。Kafka沒有限定單個消息的大小,但我們推薦消息大小不要超過1MB,通常一般消息大小都在1~10kB之前。
3.consumer
Kafka提供了兩套consumer api,分為high-level api和sample-api。Sample-api 是一個底層的API,它維持了一個和單一broker的連接,並且這個API是完全無狀態的,每次請求都需要指定offset值,因此,這套API也是最靈活的。
在kafka中,當前讀到消息的offset值是由consumer來維護的,因此,consumer可以自己決定如何讀取kafka中的數據。比如,consumer可以通過重設offset值來重新消費已消費過的數據。不管有沒有被消費,kafka會保存數據一段時間,這個時間周期是可配置的,隻有到了過期時間,kafka才會刪除這些數據。
High-level API封裝了對集群中一係列broker的訪問,可以透明的消費一個topic。它自己維持了已消費消息的狀態,即每次消費的都是下一個消息。
High-level API還支持以組的形式消費topic,如果consumers有同一個組名,那麼kafka就相當於一個隊列消息服務,而各個consumer均衡的消費相應partition中的數據。若consumers有不同的組名,那麼此時kafka就相當與一個廣播服務,會把topic中的所有消息廣播到每個consumer。
五、kafka核心特性
1.壓縮
我們上麵已經知道了Kafka支持以集合(batch)為單位發送消息,在此基礎上,Kafka還支持對消息集合進行壓縮,Producer端可以通過GZIP或Snappy格式對消息集合進行壓縮。Producer端進行壓縮之後,在Consumer端需進行解壓。壓縮的好處就是減少傳輸的數據量,減輕對網絡傳輸的壓力,在對大數據處理上,瓶頸往往體現在網絡上而不是CPU(壓縮和解壓會耗掉部分CPU資源)。
那麼如何區分消息是壓縮的還是未壓縮的呢,Kafka在消息頭部添加了一個描述壓縮屬性字節,這個字節的後兩位表示消息的壓縮采用的編碼,如果後兩位為0,則表示消息未被壓縮。
2.消息可靠性
從Producer端看:Kafka是這麼處理的,當一個消息被發送後,Producer會等待broker成功接收到消息的反饋(可通過參數控製等待時間),如果消息在途中丟失或是其中一個broker掛掉,Producer會重新發送(我們知道Kafka有備份機製,可以通過參數控製是否等待所有備份節點都收到消息)。
從Consumer端看:前麵講到過partition,broker端記錄了partition中的一個offset值,這個值指向Consumer下一個即將消費message。當Consumer收到了消息,但卻在處理過程中掛掉,此時Consumer可以通過這個offset值重新找到上一個消息再進行處理。Consumer還有權限控製這個offset值,對持久化到broker端的消息做任意處理。

最後更新:2017-07-18 09:02:22

  上一篇:go  快速入門阿裏雲aliyuncli-自動調用服務
  下一篇:go  300+篇2017阿裏雲熱點事件解析與實戰技術資料,免費下載(文章+PDF+視頻,持續更新中)