kafka原理解析

Apache的Kafka™是一個分佈式流平臺(a distributed streaming platform)。這到底意味着什麼?

我們認爲,一個流處理平臺應該具有三個關鍵能力:

  1. 它可以讓你發佈和訂閱記錄流。在這方面,它類似於一個消息隊列或企業消息系統。
  2. 它可以讓你持久化收到的記錄流,從而具有容錯能力。
  3. 它可以讓你處理收到的記錄流。

Kafka擅長哪些方面?

它被用於兩大類應用:

  1. 建立實時流數據管道從而能夠可靠地在系統或應用程序之間的共享數據
  2. 構建實時流應用程序,能夠變換或者對數據
  3. 進行相應的處理。

想要了解Kafka如何具有這些能力,讓我們從下往上深入探索Kafka的能力。

首先,明確幾個概念:

  • Kafka是運行在一個或多個服務器的集羣(Cluster)上的。
  • Kafka集羣分類存儲的記錄流被稱爲主題(Topics)。
  • 每個消息記錄包含一個鍵,一個值和時間戳。

分佈式消息系統kafka的提供了一個生產者、緩衝區、消費者的模型

 

broker:中間的kafka cluster,存儲消息,是由多個server組成的集羣

topic:kafka給消息提供的分類方式。broker用來存儲不同topic的消息數據

producer:往broker中某個topic裏面生產數據

consumer:往broker中某個topic獲取數據

設計思想

topic與消息

kafka將所有消息組織成多個topic的形式存儲,而每個topic又可以拆分成多個partition,每個partition又由一個一個消息組成。每個消息都被標識了一個遞增序列號代表其進來的先後順序,並按順序存儲在partition中。

 

這樣,消息就以一個個id的方式,組織起來。

producer選擇一個topic,生產消息,消息會通過分配策略append到某個partition末尾

consumer選擇一個topic,通過id指定從哪個位置開始消費消息。消費完成之後保留id,下次可以從這個位置開始繼續消費,也可以從其他任意位置開始消費

這個id,在kafka中被稱爲offset

這種組織和處理策略提供瞭如下好處:

消費者可以根據需求,靈活指定offset消費

保證了消息不變性,爲併發消費提供了線程安全的保證。每個consumer都保留自己的offset,互相之間不干擾,不存在線程安全問題

消息訪問的並行高效性。每個topic中的消息被組織成多個partition,partition均勻分配到集羣server中。生產、消費消息的時候,會被路由到指定partition,減少競爭,增加了程序的並行能力

增加消息系統的可伸縮性。每個topic中保留的消息可能非常龐大,通過partition將消息切分成多個子消息,並通過負責均衡策略將partition分配到不同server。這樣當機器負載滿的時候,通過擴容可以將消息重新均勻分配

保證消息可靠性。消息消費完成之後不會刪除,可以通過重置offset重新消費,保證了消息不會丟失

靈活的持久化策略。可以通過指定時間段(如最近一天)來保存消息,節省broker存儲空間

消息以partition爲單位分配到多個server,並以partition爲單位進行備份。備份策略爲:1個leader和N個followers,leader接受讀寫請求,followers被動複製leader。leader和followers會在集羣中打散,保證partition高可用

producer

producer生產消息需要如下參數:

topic:往哪個topic生產消息

partition:往哪個partition生產消息

key:根據該key將消息分區到不同partition

message:消息

根據kafka源碼,可以根據不同參數靈活調整生產、分區策略

iftopic isNonethrowErrorp=NoneifpartitionNotNoneifpartition< 0Orpartition>= numPartitions throwErrorp=partitionelif key NotNonep=hash(key) % numPartitionselsep=round-robin() % numPartitionssend message to the partitionp

上面是我翻譯的僞代碼,其中round-robin就是簡單輪詢,hash採用的是murmurhash

consumer

傳統消息系統有兩種模式:

隊列

發佈訂閱

kafka通過consumer group將兩種模式統一處理

每個consumer將自己標記consumer group名稱,之後系統會將consumer group按名稱分組,將消息複製並分發給所有分組,每個分組只有一個consumer能消費這條消息。

於是推理出兩個極端情況:

當所有consumer的consumer group相同時,系統變成隊列模式

當每個consumer的consumer group都不相同時,系統變成發佈訂閱

多consumer併發消費消息時,容易導致消息亂序

通過限制消費者爲同步,可以保證消息有序,但是這大大降低了程序的併發性。

kafka通過partition的概念,保證了partition內消息有序嗎,緩解了上面的問題。partition內消息會複製分發給所有分組,每個分組只有一個consumer能消費這條消息。這個語義保證了某個分組消費某個分區的消息,是同步而非併發的。如果一個topic只有一個partition,那麼這個topic併發消費有序,否則只是單個partition有序。

一般消息消息系統,consumer存在兩種消費模型:

push:優勢在於消息實時性高。劣勢在於沒有考慮consumer消費能力和飽和情況,容易導致producer壓垮consumer

pull:優勢在可以控制消費速度和消費數量,保證consumer不會出現飽和。劣勢在於當沒有數據,會出現空輪詢,消耗cpu

kafka採用pull,並採用可配置化參數保證當存在數據並且數據量達到一定量的時候,consumer端才進行pull操作,否則一直處於block狀態

kakfa採用整數值consumer position來記錄單個分區的消費狀態,並且單個分區單個消息只能被consumer group內的一個consumer消費,維護簡單開銷小。消費完成,broker收到確認,position指向下次消費的offset。由於消息不會刪除,在完成消費,position更新之後,consumer依然可以重置offset重新消費歷史消息

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