邊學邊記-Kafka

Kafka是一種高吞吐量的分佈式發佈訂閱消息系統

kafka名詞解釋

1、消息生產者:即:Producer,是消息的產生的源頭,負責生成消息併發送到Kafka服務器上。

2、消息消費者:即:Consumer,是消息的使用方,負責消費Kafka服務器上的消息。

3、主題:即:Topic,由用戶定義並配置在Kafka服務器,用於建立生產者和消息者之間的訂閱關係:生產者發送消息到指定的Topic下,消息者從這個Topic下消費消息。

4、消息分區:即:Partition,一個Topic下面會分爲很多分區,例如:“kafka-test”這個Topic下可以分爲6個分區,分別由兩臺服務器提供,那麼通常可以配置爲讓每臺服務器提供3個分區,假如服務器ID分別爲0、1,則所有的分區爲0-0、0-1、0-2和1-0、1-1、1-2。Topic物理上的分組,一個 topic可以分爲多個 partition,每個 partition 是一個有序的隊列。partition中的每條消息都會被分配一個有序的 id(offset)。

5、Broker:即Kafka的服務器,用戶存儲消息,Kafa集羣中的一臺或多臺服務器統稱爲 broker。

Message在Broker中通Log追加的方式進行持久化存儲。並進行分區(patitions)

爲了減少磁盤寫入的次數,broker會將消息暫時buffer起來,當消息的個數(或尺寸)達到一定閥值時,再flush到磁盤,這樣減少了磁盤IO調用的次數。

6、消費者分組:Group,用於歸組同類消費者,在Kafka中,多個消費者可以共同消息一個Topic下的消息,每個消費者消費其中的部分消息,這些消費者就組成了一個分組,擁有同一個分組名稱,通常也被稱爲消費者集羣。

Kafka中的Message是以topic爲基本單位組織的,不同的topic之間是相互獨立的。每個topic又可以分成幾個不同的partition(每個topic有幾個partition是在創建topic時指定的),每個partition存儲一部分Message。

Kafka一些重要設計思想

  • Consumergroup:各個consumer可以組成一個組,每個消息只能被組中的一個consumer消費,如果一個消息可以被多個consumer消費的話,那麼這些consumer必須在不同的組。

  • 消息狀態:在Kafka中,消息的狀態被保存在consumer中,broker不會關心哪個消息被消費了被誰消費了,只記錄一個offset值(指向partition中下一個要被消費的消息位置),這就意味着如果consumer處理不好的話,broker上的一個消息可能會被消費多次。

  • 消息持久化:Kafka中會把消息持久化到本地文件系統中,並且保持極高的效率。

  • 消息有效期:Kafka會長久保留其中的消息,以便consumer可以多次消費,當然其中很多細節是可配置的。

  • 批量發送:Kafka支持以消息集合爲單位進行批量發送,以提高push效率。

  • push-and-pull : Kafka中的Producer和consumer採用的是push-and-pull模式,即Producer只管向broker push消息,consumer只管從broker pull消息,兩者對消息的生產和消費是異步的。

  • Kafka集羣中broker之間的關係:不是主從關係,各個broker在集羣中地位一樣,我們可以隨意的增加或刪除任何一個broker節點。

  • 負載均衡方面: Kafka提供了一個 metadata API來管理broker之間的負載(對Kafka0.8.x而言,對於0.7.x主要靠zookeeper來實現負載均衡)。

  • 同步異步:Producer採用異步push方式,極大提高Kafka系統的吞吐率(可以通過參數控制是採用同步還是異步方式)。

  • 分區機制partition:Kafka的broker端支持消息分區,Producer可以決定把消息發到哪個分區,在一個分區中消息的順序就是Producer發送消息的順序,一個主題中可以有多個分區,具體分區的數量是可配置的。分區的意義很重大,後面的內容會逐漸體現。

消息隊列分類:點對點和發佈/訂閱兩種:

1、點對點:

消息生產者生產消息發送到queue中,然後消息消費者從queue中取出並且消費消息。

消息被消費以後,queue中不再有存儲,所以消息消費者不可能消費到已經被消費的消息。Queue支持存在多個消費者,但是對一個消息而言,只會有一個消費者可以消費。

2、發佈/訂閱:

消息生產者(發佈)將消息發佈到topic中,同時有多個消息消費者(訂閱)消費該消息。和點對點方式不同,發佈到topic的消息會被所有訂閱者消費。

 Kafka Topic&Partition

消息發送時都被髮送到一個topic,其本質就是一個目錄,而topic由是由一些Partition Logs(分區日誌)組成

每個Partition中的消息都是有序的

生產的消息被不斷追加到Partition log上,其中的每一個消息都被賦予了一個唯一的offset值。

Kafka集羣會保存所有的消息,不管消息有沒有被消費;我們可以設定消息的過期時間,只有過期的數據纔會被自動清除以釋放磁盤空間。比如我們設置消息過期時間爲2天,那麼這2天內的所有消息都會被保存到集羣中,數據只有超過了兩天才會被清除。

Kafka需要維持的元數據只有一個–消費消息在Partition中的offset值,Consumer每消費一個消息,offset就會加1。其實消息的狀態完全是由Consumer控制的,Consumer可以跟蹤和重設這個offset值,這樣的話Consumer就可以讀取任意位置的消息。

把消息日誌以Partition的形式存放有多重考慮,第一,方便在集羣中擴展,每個Partition可以通過調整以適應它所在的機器,而一個topic又可以有多個Partition組成,因此整個集羣就可以適應任意大小的數據了;第二就是可以提高併發,因爲可以以Partition爲單位讀寫了

Replications、Partitions 和Leaders

通過上面介紹的我們可以知道,kafka中的數據是持久化的並且能夠容錯的。Kafka允許用戶爲每個topic設置副本數量,副本數量決定了有幾個broker來存放寫入的數據。如果你的副本數量設置爲3,那麼一份數據就會被存放在3臺不同的機器上,那麼就允許有2個機器失敗。一般推薦副本數量至少爲2,這樣就可以保證增減、重啓機器時不會影響到數據消費。如果對數據持久化有更高的要求,可以把副本數量設置爲3或者更多。

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

Producers

Producers直接發送消息到broker上的leader partition,不需要經過任何中介一系列的路由轉發。爲了實現這個特性,kafka集羣中的每個broker都可以響應producer的請求,並返回topic的一些元信息,這些元信息包括哪些機器是存活的,topic的leader partition都在哪,現階段哪些leader partition是可以直接被訪問的。

Producer客戶端自己控制着消息被推送到哪些partition。實現的方式可以是隨機分配、實現一類隨機負載均衡算法,或者指定一些分區算法。Kafka提供了接口供用戶實現自定義的分區,用戶可以爲每個消息指定一個partitionKey,通過這個key來實現一些hash分區算法。比如,把userid作爲partitionkey的話,相同userid的消息將會被推送到同一個分區。

以Batch的方式推送數據可以極大的提高處理效率,kafkaProducer可以將消息在內存中累計到一定數量後作爲一個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核心特性

壓縮

我們上面已經知道了Kafka支持以集合(batch)爲單位發送消息,在此基礎上,Kafka還支持對消息集合進行壓縮,Producer端可以通過GZIP或Snappy格式對消息集合進行壓縮。Producer端進行壓縮之後,在Consumer端需進行解壓。壓縮的好處就是減少傳輸的數據量,減輕對網絡傳輸的壓力,在對大數據處理上,瓶頸往往體現在網絡上而不是CPU(壓縮和解壓會耗掉部分CPU資源)。

那麼如何區分消息是壓縮的還是未壓縮的呢,Kafka在消息頭部添加了一個描述壓縮屬性字節,這個字節的後兩位表示消息的壓縮採用的編碼,如果後兩位爲0,則表示消息未被壓縮。

消息可靠性

在消息系統中,保證消息在生產和消費過程中的可靠性是十分重要的,在實際消息傳遞過程中,可能會出現如下三中情況:

  • 一個消息發送失敗

  • 一個消息被髮送多次

  • 最理想的情況:exactly-once ,一個消息發送成功且僅發送了一次

有許多系統聲稱它們實現了exactly-once,但是它們其實忽略了生產者或消費者在生產和消費過程中有可能失敗的情況。比如雖然一個Producer成功發送一個消息,但是消息在發送途中丟失,或者成功發送到broker,也被consumer成功取走,但是這個consumer在處理取過來的消息時失敗了。

從Producer端看:Kafka是這麼處理的,當一個消息被髮送後,Producer會等待broker成功接收到消息的反饋(可通過參數控制等待時間),如果消息在途中丟失或是其中一個broker掛掉,Producer會重新發送(我們知道Kafka有備份機制,可以通過參數控制是否等待所有備份節點都收到消息)。

從Consumer端看:前面講到過partition,broker端記錄了partition中的一個offset值,這個值指向Consumer下一個即將消費message。當Consumer收到了消息,但卻在處理過程中掛掉,此時Consumer可以通過這個offset值重新找到上一個消息再進行處理。Consumer還有權限控制這個offset值,對持久化到broker端的消息做任意處理。

備份機制

備份機制是Kafka0.8版本的新特性,備份機制的出現大大提高了Kafka集羣的可靠性、穩定性。有了備份機制後,Kafka允許集羣中的節點掛掉後而不影響整個集羣工作。一個備份數量爲n的集羣允許n-1個節點失敗。在所有備份節點中,有一個節點作爲lead節點,這個節點保存了其它備份節點列表,並維持各個備份間的狀體同步。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章