kafka-一些我在學習中的理解

組件結構

  • 定位:流式處理平臺
  • 做用:消息中間件、存儲系統、實時流處理
  • kafka組件:消費者、生產者、topic、broker、streams、connecter
  • 一個典型的Kafka集羣中包含若干Producer(能夠是web前端產生的Page View,或者是服務器日誌,系統CPU、Memory等),若干broker(Kafka支持水平擴展,通常broker數量越多,集羣吞吐率越高),若干Consumer Group,以及一個Zookeeper集羣。Kafka經過Zookeeper管理集羣配置,選舉leader,以及在Consumer Group發生變化時進行rebalance。Producer使用push模式將消息發佈到broker,Consumer使用pull模式從broker訂閱並消費消息。
  • broker : 經紀人,至關於一個kafka服務器,管理該服務器中的全部不一樣topic 的分區
  • topic:至關於一個消息隊列,能夠將topic進行分區,全部分區組合起來爲一個topic的全部消息。分區能夠分佈在不一樣的服務器也能夠分佈在同一服務器。
  • 分區(partition):topic的物理上的分區,每一個partition是一個有序的隊列,每一個分區又會有leader 分區 和 follower 分區,全部的消費請求所有由leader處理,follower被動備份leader中的數據分佈在kafka集羣中不一樣的服務器中,當leader掛了以後,在follower中選擇一個做爲leader提供服務。partition由多個 segment文件組成(log文件)。消費者能夠指定分區,生產者也能夠指定分區,這種設計風格,讓消費者能夠對敏感性的消息進行局部處理。
  • offset:partition中的每一個消息都有一個連續的序列號叫作offset,用於partition惟一標識一條消息.
  • segment文件:partition物理上由segment文件組成,
  • 消費模式:點對點模式(隊列模式,一個消費者對應一個消息隊列,每一個消費隊列也只能對應一個),發佈訂閱模式(topic 與 消費者爲多多對應關係 )
  • kafka中的消費模式實現,kafka爲這兩種的消費模型提供了統一的消費者抽象模型:消費者組
    • 點對點模式:消費組的概念,假設一個topic被消費,全部的消費這個topic的消費者都在一個消費組中,那麼就能夠看做是點對點模式了
    • 發佈訂閱模式:一個topic被消費,全部消費這個topic的消費者再也不一個組中,多個組消費同一個topic 那麼就是該模型
  • 消費者組:每一個消費者都有消費者組標識,標識本身屬於哪個消費者組,消費者組去訂閱topic,topic的數據被消費者組的消費者均分,一個分區對應一個消費者。若是一個消費者組有3個實例,一個topic有2個分區,則會有一個消費者永遠獲取不到數據。 一個消費者組只能對應一個topic,組中的每一個消費者對應topic的一個分區,在初始化階段,消費者隨機選擇分區(也能夠手動分配不過較複雜)。一個topic能夠被多個消費者組消費。topic和消費者組是一對多的關係。因此,注意相同的消費者組中不能有比分區更多的消費者,不然多出的消費者一直處於空等待,不會收到消息。
  • streams:負責處理消息在kafka中的流轉,信息流的處理直接使用producer和consumer API進行簡單的處理。對於複雜的轉換,Kafka提供了更強大的Streams API。可構建聚合計算或鏈接流到一塊兒的複雜應用程序。完成實時流處理。 Sterams API在Kafka中的核心:使用producer和consumer API做爲輸入,利用Kafka作狀態存儲,使用相同的組機制在stream處理器實例之間進行容錯保障。
  • connecter:負責將kafka鏈接到不一樣的數據存儲系統,好比mysql數據庫,txt文件等
  • 消息順序性:kafka只能保證一個topic中一個分區的消息順序性,一個topic中的多個分區沒法保證順序一致性,要想保證一個topic的順序一致性只能將topic 設定爲一個分區。
  • 複製因子: 是相對於topic的分區來定義的,若是一個topic的複製因子設置爲N,分區的leader+follower的數量爲N,則該topic容許N-1服務器宕機而不丟失任何已經提交(committed)的消息。

存儲結構

  • 文件系統具體看另外一篇筆記
  • kafka文件系統:指的是partition中segment文件(log、index)的存儲結構
  • kafka使用文件系統並依賴頁緩存(page cache)來保證在宕機緩存保持可用、存儲大量消息的狀況下的常數複雜度獲取消息數據。
  • 每一個topic的partition是一個大文件夾,裏面有許多segment文件夾,
  • 頁緩存是將磁盤中的對應的數據頁加載到預先分配好的內存中等待進程使用,具備預讀和替換的功能。
  • 當內存空間耗盡時,能夠將消息數據 flush到磁盤中,而沒必要要儘量的把數據維持在內存中。
  • kafka的存儲是以頁緩存爲中心進行設計的
  • 設計存儲結構的主要目的:提升磁盤利用率和消息處理性能。
  • 事實上,kafka無需任何性能損失既能夠訪問幾乎無限制的磁盤空間,這意味着能夠提供通常消息傳遞系統沒法提供的特性。 例如,在Kafka中,消息被消費後不是立馬被刪除,咱們能夠保留消息相對較長的時間(例如一個星期)。 這將爲消費者帶來很大的靈活性
  • 如何保證常數時間複雜度獲取消息
    • 選擇消費的topic
    • 負載均衡找到對應的partition,非初次則找到該消費線程對應的partition
    • 根據記錄的offset二分法查找partition對應segment文件(log file and index file),並將其讀入到頁緩存中,採用零拷貝的方式將所需數據發送到網卡緩衝區 O(1)
    • 查找對應index文件,在index文件中找到對應的物理地址,找到消息

高吞吐量

Kafka 高吞吐依賴的主要有三點:前端

  1. micro-batch處理方式,也就是當前Spark Streaming(實時流處理框架)所使用的模式,不是一條條的發送消息,而是一小批一小批的處理。經過微乎其微的延時消耗換取吞吐量幾百倍的提高。這種方式也更讓Kafka像是一個流處理框架,而且如今Kafka也已經被用於一些流處理的場景了。 Kafka經過遞歸消息集來支持這一點。 一批消息能夠一塊兒壓縮並以此形式發送到服務器。 這批消息將以壓縮形式寫入,並將在日誌中保持壓縮,而且只能由消費者解壓縮。Kafka支持GZIP和Snappy壓縮協議
  2. 使用追加寫的方式(順序寫):這一點相當重要,咱們知道在普通的機械硬盤中隨機讀寫和順序讀寫速度差別徹底不是一個數量級的,SSD順序讀、機械硬盤順序讀的速度甚至比內存的隨機讀速度還要高。熟知操做系統的話,都很清楚磁盤讀寫操做的主要時間消耗是由於機械操做的循道等消耗。
  3. Linux中的sendfile的零拷貝加持,所謂的零拷貝其實就是本來一份數據的IO是須要通過屢次copy操做&內核態與用戶態的上下文切換,讀內核態緩存到應用程序緩存再從應用程序緩存到Socket緩存完成具體的IO操做,而sendFile系統調用零拷貝就是避免了上下文切換帶來的copy操做,同時利用直接存儲器訪問技術(DMA)執行IO操做,避免了內核緩衝區以前的數據拷貝操做。上升到上層的語言操做,就是使用的Java中的FileChannel.transferTo方法進行實現的。(Kafka 1版本使用的是Scala,2版本開始就是使用Java 了這二者都是在JVM上執行的,本質.class 文件解析執行階段實際上是一致的)

非零拷貝:用戶進程獲取數據而且將數據經過網絡發送到調用者方的過程須要四次數據拷貝,兩次系統調用,兩次用戶態內核態上下文切換: 1:操做系統經過DMA將數據從磁盤拷貝到內核空間的頁緩存中 2:經過系統調用將頁緩存的數據拷貝到用戶進程的空間緩存中 3:用戶進程要經過網絡將數據發送到目標方,則須要經過系統調用將用戶進程的緩存數據發送到內核空間中的socket緩存中 4:內核空間中操做系統經過DMA將socket 緩存中的數據發送到網卡緩衝區中mysql

零拷貝(zero-copy):kafka使用sendfile()方式,只有消費(pull)消息時纔會適用零拷貝,push消息時可能會對消息進行一些處理,這必需要將數據拷貝到用戶態進行處理。 數據傳送只發生的內核空間,沒有上下文切換,容許操做系統直接將頁緩存中的數據發送到網絡中,過程爲: 1:操做系統經過DMA將數據從磁盤拷貝到內核空間的頁緩存中 2:將帶有文件位置和長度信息的緩衝區描述符添加socket緩衝區,這一步不復制頁緩存中的數據 3:操做系統經過描述符信息直接將頁緩存中的數據發送到網卡緩衝區 零拷貝技術有多種,每一種有其適用場景和侷限性,好比上述kafka適用的零拷貝技術就是使用的sendfile,而且須要硬件已經驅動程序支持(好比上述的第三步就須要硬件和驅動程序來支持了),其餘的還有mmap、splice等具體請看:linux中零拷貝技術筆記linux

  1. 標準化二進制數據格式,在consumer、products、broker中間的流轉的消息數據塊採用同一種二進制格式,減小格式轉換,提升吞吐量
  2. 數據壓縮傳輸,kafka支持多種數據壓縮格式。

負載均衡&故障轉移

  • 負載均衡nginx

    • kafka是一種分佈式的消息系統,要作負載均衡,也就是要作到均勻分配到全部參與工做的服務器。這裏Kafka使用的是分區只能領導者選舉,也就是來均勻的選擇分區,保證各個分區收到的請求消息都是大體均勻的。
    • Kafka中有一個叫作partition的概念,也就是分區選擇器,默認使用的是murmur2Hash 算法計算消息key值的hash值,而後對於總分區數進行求模獲得對應的目標分區號,murmur2Hash是一種比較先進的Hash算法,而且在有規律的輸入時也能保證分佈較爲均勻,使用這個算法的還有redis(當字典被用做數據庫的底層實現或者hash鍵的底層實現時,來計算鍵的哈希值)、nginx、Hadoop。除此以外,使用者能夠自定義對應的
  • 故障轉移web

    • 常見的故障轉移實現策略的關鍵一般是故障發現,Kafka依賴的是zk的 心跳檢測機制,當一臺Kafka服務器啓動後將會話註冊到Zookeeper中,
    • zk不停的對節點進行心跳檢測,故障發生時與Zookeeper的會話沒法維持致使鏈接超時從而發現故障,此時請求就再也不打到這臺機器,而且選舉出一臺新的Kafka服務器來替代這臺故障的Kafka服務器。 另一種狀況,若是節點爲一個slave,那麼不能落後leader太多。這也會致使將該節點斷定爲故障,這裏的落後太多可能兩個緣由致使一個是網絡太慢致使複製太慢從而落後太多,另一個就是卡主好屢次leader 向slave複製都沒有做用。 落後是經過replica.lag.max.messages配置控制,卡住是經過replica.lag.time.max.ms配置控制的。

伸縮性

如何輕易的向kafka集羣中增長計算資源,而且保證計算資源儘量的線形疊加。在分佈式系統中伸縮性一直是一個較大的問題,由於僅僅是增長機器資源一般會由於一些隱藏的單點瓶頸致使沒法線線形擴容,好比說最大的因素就是服務狀態的保存。「狀態的處理」好比一致性,須要維持狀態的一致性就須要浪費大量的cpu資源,因此爲了下降這種消耗,Kafka將絕大部分的狀態保存及維持相關的交給kafka controller(被zk選舉出來的broker) 統一管理。Kafka 服務器內部僅維持少許暫時須要的狀態。redis

每一條消息被髮送到Kafka中,其會根據必定的規則選擇被存儲到哪個partition中。若是規則設置的合理,全部的消息能夠均勻分佈到不一樣的partition裏,這樣就實現了水平擴展算法

消費與生產消息

  • 消費者消費消息所採用的方式:pull或者push?
    • 這裏的pull和push都是相對於消費者來講的
    • 第一種是服務器push給消費者,優勢是一點服務端數據有變消費者能夠立馬感知到變化,缺點是沒法預估消費者消費能力可能形成消息堆積
    • 第二種消費者主動pull服務器,優勢能夠適應消費者自身的消費速度還能夠消費者指定消費消息量批處理傳輸消息,缺點是若是服務器沒有數據,則消費者會一直輪詢服務器形成計算機資源浪費,優化的手段能夠採用long poll長輪詢。
    • 在kafka中使用的是pull加long poll的方式
  • 如何保證消費者與broker消費的消息達成一致?
    • kafka也沒法達成徹底一致,可是對一致性作了輕量化處理,其處理方式爲,每一個topic的partition徹底有序,每個partition只對應消費組中的一個消費者,這樣消費者在每一個分區中的位置只須要一個整數(offset)便可。這可使得已經消費到哪裏位置的狀態變得特別小,每一個分區只有一個數字,能夠進行按期檢查,這樣的設計使得消息的應答(消費者消費消息的確認)更加輕量。
    • 這種非徹底一致性可能致使消息的重複消費,好比:消費者消費了數據,可是應答數據在網絡中丟失,這就會致使offset不是最新的,致使消息重複消費
  • kafka對於消費者和生產者默認支持的是「至少一次(at lwast once)」語義
    • 讀取消息->處理消息->ack到broker->修改offset
    • 只要「ack到broker」這步丟失,那麼消息可能會重複消費,這也知足最少一次語義。
  • broker如何保證生產者消息不重複?
    • 在版本0.11以後,kafka提供冪等性機制,broker爲每一個生產者分配一個ID,並經過生產者發送的序列號爲每一個消息進行去重。即便生產者push消息後「收到確認」在網絡中丟失致使從新發送message,在broker中也不會保存重複的message。

若是您不一樣理解,請在評論出指出,共同窗習!sql

若是感受這篇文章對您有所幫助,請點擊一下「喜歡」或者「關注」博主,您的喜歡和關注將是我前進的最大動力!數據庫

相關文章
相關標籤/搜索