kafka是一種高吞吐量的分布式發(fā)布訂閱消息系統(tǒng),有如下特性:

1. 通過O(1)的磁盤數據結構提供消息的持久化,這種結構對于即使數以TB的消息存儲也能夠保持長時間的穩(wěn)定性能。

2 .高吞吐量:即使是非常普通的硬件kafka也可以支持每秒數十萬的消息。

3 .支持通過kafka服務器和消費機集群來分區(qū)消息。

4 .支持Hadoop并行數據加載。

 本篇屬于大數據技術-> kafka 系列的開篇,本文從以下幾個基礎層面概述Kafka的知識點,后續(xù)在針對于單個的技術點擴展每篇博文。

  • Kafka背景介紹

  • Kafka基本架構組件

  • Kafka設計原理

  • Kafka用途


一:Kafka背景介紹

Kafka是一種高吞吐量的,分布式,快速、可擴展的,分區(qū)和可復制,基于發(fā)布/訂閱模式的消息系統(tǒng),由Linkedin開發(fā),之后成為Apache項目的一部分。使用Scala語言編寫,目前已被廣泛應用于各行業(yè)各類型的數據管道和消息系統(tǒng)中。

kafka的設計目的是提供一個發(fā)布訂閱解決方案,它可以處理消費者規(guī)模的網站中的所有動作流數據。 這種動作(網頁瀏覽,搜索和其他用戶的行動)是在現代網絡上的許多社會功能的一個關鍵因素。 這些數據通常是由于吞吐量的要求而通過處理日志和日志聚合來解決。

Kafka分布式發(fā)布訂閱設計圖

二 :Kafka基本架構組件

1. Broker :[中間者,代理者]

   Kafka集群包含多臺服務器,一臺Kafka服務器就是一個Broker,一個集群由多個broker組成,一個broker可以有多個topic。broker承擔著中間緩存和分發(fā)的作用,broker將producer發(fā)送的數據分發(fā)到注冊consumer中

2. Topic :

  topic[主題,類別,話題],我們可以理解為是一種隊列,每條發(fā)送消息都從屬于一種類別,這種類別在kafka中被設計為一個topic,比如:用戶信息類的消息的topic,我們定義為user-topic,那么凡是用戶信息類的消息都將發(fā)送到這個topic中,從而我們所要處理用戶信息類的消費者就可以從這topic中拉取。

3. Producer :

  producer是生產者,意在向Topic中發(fā)送消息的一方

4. Consumer  :

  consumer是消費者,意在向Topic中拉?。M消息的一方

Kafka拓撲結構

電腦培訓,計算機培訓,平面設計培訓,網頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

如上圖所示,一個典型的Kafka集群中包含若干Producer,若干broker(Kafka支持水平擴展,一般broker數量越多,集群吞吐率越高),若干Consumer Group,以及一個Zookeeper集群。Kafka通過Zookeeper管理集群配置,選舉leader,以及在Consumer Group發(fā)生變化時進行rebalance。Producer使用push模式將消息發(fā)布到broker,Consumer使用pull模式從broker訂閱并消費消息。

5. Partition :

  Kafka內在就是分布式的,一個broker中可以有多個topic,一個topic可以設置多個partition(分區(qū)),每個Partition在物理上都對應一個文件夾,該文件夾存儲這個Partition的所有消息和索引文件。Partition中的消息都會被分配為一個有序的ID(offset),一個partition對應多個Segment,每個Segment對應一個文件,Segment由一個個的不可變記錄組成,該記錄只會append到Segment中,不會單獨的修改或者刪除,可以設置Segment根據時間或者大小來定時刪除文件。默認是根據大小128MB,當segment大小達到128MB時,則會刪除一些Segment文件(這里有一點,刪除的時候,會選擇一個或者多個Segment來刪除,也就是說刪除三個Segment大小可能大于128MB,但是不會是小于128MB)

電腦培訓,計算機培訓,平面設計培訓,網頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

6.offset :偏移,在每個partition分區(qū)下的消息都是順序保存的,kakfa使用一個唯一的標識來記錄它們在該分區(qū)下的位置,這個位置標識被稱為offset(位移),位移是順序遞增的,一旦確定下來之后就不能修改。Kafka會維護分區(qū)下的消息順序,但是不會維護跨partition(分區(qū))間的順序(假如,我們往topic1分別發(fā)送三條消息1,2,3 那么,1和3發(fā)送到了partition1中,2發(fā)送到了partition2中,那么kafka consumer在消費時,會按照1 然后 3的順序消息,但是不保證 2 會在消費1之后在消費 )

那么我們知道了topic,partition和offset信息,我們就能唯一定位一條消息。所以說每條Kafka的消息本質上都是一個三元組(tuple):<topic, partition, offset>。我們可以稱該三元組為消息的元數據(message metadata)。它們之間的關系如下圖所示:

  電腦培訓,計算機培訓,平面設計培訓,網頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

三 :Kafka設計原理

We designed Kafka to be able to act as a unified platform for handling all the real-time data feeds a large company might have. To do this we had to think through a fairly broad set of use cases.

Kafka是一個消息引擎(messaging system),Kafka本身提供了用于消息傳遞的一套完整功能及接口,而不僅僅是提供消息的表示。大型系統(tǒng)之間數據交互基本上都需要這樣的消息引擎。作為一個基礎設施,Kafka即扮演了這樣的角色。

1  . 持久化(Persistence) 

Kafka是高度依賴文件系統(tǒng)和緩存的,Kafka對磁盤時append操作,磁盤檢索的開支是較少的,同時為了減少磁盤寫入的次數,broker會將消息暫時buffer起來,當消息的數量(offset)達到一定閥值時(可配置 offset可以設置為自動提交或者手動提交),再flush到磁盤中,這樣減少了磁盤的開銷。

2 . 生產者(producer)

producer用于往broker中發(fā)送/生產消息,每一個broker中可以有多個topic,每個topic下面又會有多個partition,在負載均衡的情況,如果均衡的將消息發(fā)送到指定的partition中.(對于具體的producer在以后會有詳細的介紹)

   異步處理:將多條消息存儲在buffer中,之后,批量的提交到broker中,從而提高了網絡IO,但是也有一點,采用異步發(fā)送機制如果producer異?;蛘邔嵭?,那么消息將會丟失。

3 .消費者(Consumer)

  Consumer通過鏈接broker,采用pull方式來拉取broker中的數據,consumer根據自己的消費能力,去消費信息。那么這里為什么采用pull而不是push呢?因為pull模式中1:broker是不需要感知有多少個consumer。2:如果采用push模式一旦消息量級超過consumer的承受范圍,會壓垮consumer。

前面我們說過,topic屬于一個類別,topic由多個有序的partition序列組成,每個partition在同一時刻只會被一個consumer進行消費,同時會更新offset的index,記錄消費到的位置,在consumer每消費完一條信息之后,kafka會自動的提交offset,當然我們也可以設置為手動提交,當我們在消費100000條消息之后,offset存儲在一個list中,達到一定的消息量之后,提交這個offset list。

4 .常量時間存儲能力

  一個實現了數據持久化的隊列,提供簡單的數據讀和數據追加寫到文件末尾,例如在一個日志管理系統(tǒng)中。這種數據結構的最大優(yōu)勢是所有操作的算法復雜度都是O(1),磁盤讀、寫也不會互相阻塞。這使得Kafka具有了一個顯著的性能優(yōu)勢,因為在這里性能與數據量實現了完全得解耦。一臺服務器現在可以輕松利用到一組廉價的低轉速、大容量(1+TB)磁盤能夠提供的各種優(yōu)勢,雖然這些磁盤只有可憐的尋道速度但仍然能夠基于大塊數據的讀、寫提供可以接受的性能。這些磁盤普遍只有SAS磁盤價格的1/3和3倍以上的容量。

       擁有訪問幾乎無限的磁盤空間的能力,卻不會有任何性能懲罰,這意味著我們可以基于Kafka實現一些在傳統(tǒng)消息中間件中很少看到的特性。例如,在傳統(tǒng)消息中間件系統(tǒng)中往往會在消息一旦被獲取后立即嘗試刪除該消息數據,而Kafka能夠為消息數據保留一個相對來說很長的時間(如一周)。僅這一個特性,就為消息消費端提供了大量的靈活性。 

5 .消費分發(fā)機制

  1. At most once 消息可能會丟,但絕不會重復傳輸

  2. At least one 消息絕不會丟,但可能會重復傳輸

  3. Exactly once 每條消息肯定會被傳輸一次且僅傳輸一次,很多時候這是用戶所想要的

當Producer向broker發(fā)送消息時,一旦這條消息被commit,因數replication的存在,它就不會丟。但是如果Producer發(fā)送數據給broker后,遇到網絡問題而造成通信中斷,那Producer就無法判斷該條消息是否已經commit。雖然Kafka無法確定網絡故障期間發(fā)生了什么,但是Producer可以生成一種類似于主鍵的東西,發(fā)生故障時冪等性的重試多次,這樣就做到了Exactly once。

Consumer在從broker讀取消息后,可以選擇commit,該操作會在Zookeeper中保存該Consumer在該Partition中讀取的消息的offset。該Consumer下一次再讀該Partition時會從下一條開始讀取。如未commit,下一次讀取的開始位置會跟上一次commit之后的開始位置相同。當然可以將Consumer設置為autocommit,即Consumer一旦讀到數據立即自動commit。如果只討論這一讀取消息的過程,那Kafka是確保了Exactly once。但實際使用中應用程序并非在Consumer讀取完數據就結束了,而是要進行進一步處理,而數據處理與commit的順序在很大程度上決定了消息從broker和consumer的delivery guarantee semantic。

  • 讀完消息先commit再處理消息。這種模式下,如果Consumer在commit后還沒來得及處理消息就crash了,下次重新開始工作后就無法讀到剛剛已提交而未處理的消息,這就對應于At most once

  • 讀完消息先處理再commit。這種模式下,如果在處理完消息之后commit之前Consumer crash了,下次重新開始工作時還會處理剛剛未commit的消息,實際上該消息已經被處理過了。這就對應于At least once。在很多使用場景下,消息都有一個主鍵,所以消息的處理往往具有冪等性,即多次處理這一條消息跟只處理一次是等效的,那就可以認為是Exactly once。(筆者認為這種說法比較牽強,畢竟它不是Kafka本身提供的機制,主鍵本身也并不能完全保證操作的冪等性。而且實際上我們說delivery guarantee 語義是討論被處理多少次,而非處理結果怎樣,因為處理方式多種多樣,我們不應該把處理過程的特性——如是否冪等性,當成Kafka本身的Feature)

  • 如果一定要做到Exactly once,就需要協(xié)調offset和實際操作的輸出。精典的做法是引入兩階段提交。如果能讓offset和操作輸入存在同一個地方,會更簡潔和通用。這種方式可能更好,因為許多輸出系統(tǒng)可能不支持兩階段提交。比如,Consumer拿到數據后可能把數據放到HDFS,如果把最新的offset和數據本身一起寫到HDFS,那就可以保證數據的輸出和offset的更新要么都完成,要么都不完成,間接實現Exactly once。(目前就high level API而言,offset是存于Zookeeper中的,無法存于HDFS,而low level API的offset是由自己去維護的,可以將之存于HDFS中)

 6 .復制 Replication

  kafka將每個partition數據復制到多個server上,任何一個partition有一個leader和多個follower(可以沒有)。備份的個數可以通過broker配置文件來設定,Kafka自動維護leader和follower的失效轉移。leader處理所有的read-write請求,follower需要和leader保持同步。Follower和consumer一樣,消費消息并保存在本地日志中。leader負責跟蹤所有的follower狀態(tài),如果follower"落后"太多或者失效,leader將會把它從replicas同步列表中刪除。當所有的follower都將一條消息保存成功,此消息才被認為是"committed",此時consumer才能消費它。即使只有一個replicas實例存活,仍然可以保證消息的正常發(fā)送和接收,只要zookeeper集群存活即可(不同于其他分布式存儲,比如Hbase需要"多數派"存活才行)。當然了,在Producer端是可以通過參數”request.required.acks”來控制自己是否要等待消息返回”committed”的響應。

        當leader失效時,需在followers中選取出新的leader,當然了只有處于”in-sync”狀態(tài)的followers才有參選資格??赡艽藭rfollower落后于leader,因此需要選擇一個"up-to-date"的follower。選擇follower時需要兼顧一個問題就是新leader server上所已經承載的partition leader的個數。如果一個server上有過多的partition leader,意味著此server將承受著更多的IO壓力。在選舉新leader時需要考慮到"負載均衡"。Follower需要能夠維護和ZooKeeper之間一個有效的會話,否則也會被判定為”unalive”。一個配置參數”replica.lag.time.max.ms”控制著一個follower數據同步滯后所能允許的最大延時。 

四 :kafka應用場景

1 :消息系統(tǒng)

    kafka本身作為一個消息發(fā)布訂閱系統(tǒng),具有很好的容錯性以及可擴展性并且能夠支撐高并發(fā)的數據量,kafka使用了多種效率的優(yōu)化機制,采用來push/pull架構模式,更適合于異構集群。和大多數的消息系統(tǒng)相比,kafka具有更好的吞吐量,內置分區(qū),復制和容錯,這使得它成為一個大規(guī)模的消息處理應用程序。

 消息的使用往往是相對較低的吞吐量,但可能需要低終端到終端的延遲,往往依賴于強大的耐用性。

在這一領域的卡夫卡與傳統(tǒng)的消息傳遞系統(tǒng)如ActiveMQ和RabbitMQ。

3 :監(jiān)控

    Kafka通常被用于可操作的監(jiān)控數據。這包括從分布式應用程序來的聚合統(tǒng)計用來生產集中的運營數據提要。

4 :日志聚合

kafka的特性決定它非常適合作為"日志收集中心";application可以將操作日志"批量""異步"的發(fā)送到kafka集群中,而不是保存在本地或者DB中;kafka可以批量提交消息/壓縮消息等,這對producer端而言,幾乎感覺不到性能的開支.此時consumer端可以使Hadoop等其他系統(tǒng)化的存儲和分析系統(tǒng)