Kafka是壹個開源、輕量級、分布式、可分區且功能強大的消息系統,基於ZooKeeper的協調管理,具有復制和分布式流媒體平臺。作為壹個流處理平臺,它必須具備以下三個關鍵特征:
1)可以允許發布和訂閱流數據。
2)存儲流數據時提供相應的容錯機制。
3)流數據到達時可以及時處理。
卡夫卡信息流系統的基本結構包括生產者和消費者,以及卡夫卡集群。
生產者負責生產消息,並寫入Kafka集群;消費者從Kafka集群獲取信息。
消息是卡夫卡通信的基本單位,由定長的消息頭和變長的消息體組成。
卡夫卡把壹組信息抽象成壹個主題,即主題是信息的分類。生產者將消息指定的主題發送給kafka cluster,消費者訂閱主題或主題的某些分區進行消費。
卡夫卡把壹組信息概括成壹個主題,每個主題又分成壹個或多個分區。每個分區由壹系列有序且不可變的消息組成,這是壹個有序隊列。每個分區實際上對應壹個文件夾。分區的命名規則是主題名後跟“—”連接器,然後是分區號。分區號從0開始,最大數是分區總數減1。
分區使得Kafka在並發處理上更容易。理論上分區越多,吞吐量越高,但要看集群的實際環境和業務場景。同時,分區也是Kafka保證消息順序消費,平衡消息負載的基礎。
問答:分區如何確保消息被順序使用?每個分區的消息都是有序的,但是不同分區之間如何保證呢?猜測是分區存儲空間比較大,分區數量少。順序消耗的主要因素是分區內的消息,分區間的消息可以忽略。高吞吐量順序寫磁盤估計也是原因。
Kafka只能保證壹個分區內的消息排序,而不能保證跨分區的消息排序。每條消息都被追加到對應的分區,按順序寫到磁盤,所以效率非常高,這是Kafka高吞吐量的重要保證。同時,與傳統的消息系統不同,Kafka不會立即刪除已消費的消息,並且由於磁盤的限制,消息並不總是被存儲。因此,Kafka提供了兩種刪除舊數據的策略,壹種是基於消息存儲的時間長度,另壹種是基於分區的大小。這兩種策略都可以通過配置文件進行配置。
每個分區都有壹個或多個副本,分區的副本分布在集群的不同代理上,以提高可用性。
從存儲的角度來看,分區的每個副本都被邏輯抽象為壹個日誌對象,即分區的副本與日誌對象壹壹對應。每個主題對應的分區數量可以在Kafka啟動時加載的配置文件中配置,也可以在創建主題時指定。當然,客戶端也可以在創建主題後修改主題的分區數量。
為什麽文案要分首領和跟隨者?如果沒有Leader副本,所有副本需要同時負責讀/寫請求,同時必須保證這些副本之間數據的壹致性。假設有n個副本,需要有n×n個通道來同步數據,很難保證數據的壹致性和有序性。
為了解決這個問題,卡夫卡選擇隔板的壹個副本作為領導者,隔板的其他副本作為追隨者。只有主副本負責處理客戶端的讀/寫請求,從副本從主副本同步數據。
引入領導副本後,客戶端只需要與領導副本進行交互,這樣就保證了數據的壹致性和順序性。跟隨者副本同步來自引導者副本的消息,N個副本只需要n-1條路徑,使得系統更加簡單高效。
模仿者和領導者的角色並不固定。如果領導者失敗,將通過相應的選舉算法從追隨者的其他副本中選擇領導者的新副本。
問:領導者和追隨者副本是如何選擇的?動物園管理員選的?
Kafka在ZooKeeper中動態維護壹個ISR(In-sync Replica),即保持壹個同步的副本列表,該列表中保存了與Leader副本保持消息同步的所有副本對應的代理節點id。如果從副本關閉或落後太多,從副本節點將從ISR列表中刪除。在本書中,宕機是指代理的故障,包括但不限於代理被關閉,如代理被人為關閉或出現物理故障、檢測到過期心跳、網絡延遲、進程崩潰等。
發布到分區的任何消息都將被直接追加到日誌文件(文件名後綴為"的數據文件)的尾部。log”在分區目錄中),並且日誌文件中每個消息的位置將對應於增量偏移。Offset是分區下嚴格排序的邏輯值,不代表消息在磁盤上的物理位置。由於Kafka幾乎不允許隨機讀寫消息,因此Kafka沒有為存儲偏移量提供額外的索引機制。
消費者可以通過控制消息偏移量來消費消息,例如,消費者可以指定消費的起始偏移量。為了確保消息按順序被消費,對應於消費者已經消費的消息的偏移量也需要被保存。需要註意的是,消費者對消息偏移量的操作不會影響消息本身的偏移量。老消費者把消費抵消存進了ZooKeeper,新消費者把消費抵消存進了卡夫卡內部的壹個主題。當然,消費者也可以將消費抵消保存在外部系統中,而不保存在卡夫卡中。
推測:壹個主題有多個分區,壹個分區有多個副本。壹個主題(壹種消息)有多個分區(消息被分段),壹個分區(每條消息)有多個副本(每條消息的副本數)。壹旦消息被發送到kafka,它將被分配壹個偏移量,該偏移量在多個副本中是相同的。這樣,消費者通過抵消消費時,對於多份就沒有區別了。
Kafka集群由壹個或多個Kafka實例組成,每個Kafka實例稱為壹個代理,通常也稱為KafkaServer。在生產環境中,Kafka集群壹般包括壹個或多個服務器,我們可以在壹個服務器上配置壹個或多個代理。每個代理都有壹個唯壹的標識id,它是壹個非負整數。在Kafka集群中,每次添加代理時,都需要配置壹個不同於集群中其他代理的id。ID值可以是任意非負整數,只要保證在整個Kafka集群中唯壹即可。此id,id代理的名稱,即對應於代理啟動時配置的broker.id的值。
生產者負責將消息發送給代理,也就是將消息發送給Kafka代理的客戶端。
消費者以拉模式拉取數據,是消費的客戶端。在卡夫卡那裏,每個消費者都屬於壹個特定的消費群體。您可以為每個使用者指定壹個使用者組,使用groupId表示使用者組的名稱,並通過group.id配置設置..如果沒有指定使用者組,則該使用者屬於默認的使用者組test-consumer-group。
每個消費者都有壹個全局唯壹id,由配置項client.id指定。如果客戶端沒有指定消費者的id,Kafka將自動為消費者生成壹個全局唯壹id,格式為${ groupID }-${ hostname }-${ timestamp }-${ UUID的前8個字符}。同壹主題的消息只能由同壹消費群中的壹個消費者消費,但不同消費群中的消費者可以同時消費該消息。消費群體是卡夫卡廣播和單播壹個主題信息的手段。實現消息廣播只需要指定所有的消費者屬於不同的消費者組,而對於消息單播,所有的消費者只需要屬於同壹個消費者組。
推論:kafka消息根據消息類型(主題)只能在壹個消費群消費壹次。也就是說,壹個消費者群體只消費壹種類型的消息。如果壹個服務想要消費壹種消息,它必須將自己放入不同的消費群體中。
Kafka使用ZooKeeper保存相應的元數據信息,包括代理節點信息、Kafka集群信息、舊消費者信息及其消費偏移量信息、主題信息、分區狀態信息、分區副本分配方案信息、動態配置信息等。Kafka會在ZooKeeper上創建相應的節點來保存啟動或運行時的元數據信息。Kafka會通過監控機制在這些節點註冊相應的監聽器來監控節點元數據的變化,所以ZooKeeper會負責管理和維護Kafka集群。同時,我們可以方便地橫向擴展Kafka集群,並通過ZooKeeper遷移數據。