kafka(一)—基本概念

本文已同步至我的博客 liaosi'blog-kafka(一)—基本概念

Kafka簡介

Kafka是用scala語言編寫,最初由Linkedin公司開發,後貢獻給了Apache基金會併成爲頂級開源項目。是一個分佈式、支持分區的(partition)、多副本的(replication),基於zookeeper協調的分佈式消息系統,它的最大的特性就是能夠實時的處理大量數據以知足各類需求場景:好比基於hadoop的批處理系統、低延遲的實時系統、storm/Spark流式處理引擎,web/nginx日誌、訪問日誌,消息服務等等。mysql

Kafka是一個類JMS消息隊列,結合了JMS中的兩種模式,能夠有多個消費者主動拉取數據。雖然它提供了相似於JMS的特性,可是在設計實現上徹底不一樣,此外它並非JMS規範的實現,在JMS中只有點對點模式纔有消費者主動拉取數據。nginx

1.Kafka的特性

  • 高吞吐量、低延遲:kafka每秒能夠處理幾十萬條消息,它的延遲最低只有幾毫秒,每一個topic能夠分多個partition,consumer group 對 partition 進行consume操做。
  • 可擴展性:kafka集羣支持熱擴展
  • 持久性、可靠性:消息被持久化到本地磁盤,而且支持數據備份防止數據丟失
  • 容錯性:容許集羣中節點失敗(若副本數量爲n,則容許n-1個節點失敗)
  • 高併發:支持數千個客戶端同時讀寫
  • 順序性:由生產者發送到一個特定的主題分區的消息將被以他們被髮送的順序來追加。也就是說,
    若是一個消息M1和消息M2都來自同一個生產者,M1先發,那麼M1將有一個低於M2的偏移,會更早在日誌中出現。
    消費者看到的記錄排序就是記錄被存儲在日誌中的順序。

2.Kafka的使用場景:

  • 日誌收集:一個公司能夠用Kafka能夠收集各類服務的log,經過kafka以統一接口服務的方式開放給各類consumer,例如Hadoop、Hbase、Solr等。
  • 消息系統:解耦生產者和消費者、緩存消息等。
  • 用戶活動跟蹤:Kafka常常被用來記錄web用戶或者app用戶的各類活動,如瀏覽網頁、搜索、點擊等活動,這些活動信息被各個服務器發佈到kafka的topic中,而後訂閱者經過訂閱這些topic來作實時的監控分析,或者裝載到hadoop、數據倉庫中作離線分析和挖掘。
  • 運營指標:Kafka也常常用來記錄運營監控數據。包括收集各類分佈式應用的數據,生產各類操做的集中反饋,好比報警和報告。
  • 流式處理:好比 Spark Streaming 和 Storm。
  • 事件源

Kafka的幾個重要概念

官方文檔:Kafka官網文檔
Kafka的運行架構以下圖,各組件之間經過TCP協議通訊:web

1.Broker

kafka 集羣由多個 kafka 實例組成,每一個實例 (server) 稱爲 broker ,在集羣中每一個broker都有一個惟一brokerid,不得重複。 不管是 kafka 集羣,仍是 producer 和 consumer 都依賴於 zookeeper 來保證系統可用性,爲集羣保存一些 meta (元數據)信息。算法

2.Topics And Logs

主題(topic)是一種分類或發佈的一系列記錄的名義上的名字。Kafka的主題始終是支持多用戶訂閱的;也就是說,一個主題能夠有零個,一個或多個消費者訂閱寫入的數據。
對於每個主題,Kafka集羣保持一個分區日誌文件,看下圖:sql

每一個分區都由一系列有序的、不可變的消息組成,這些消息被連續的追加到分區中。分區中的每一個消息都有一個連續的序列號叫作offset,用來在分區中惟一的標識這個消息。apache

在一個可配置的時間段內,Kafka集羣保留全部發布的消息,無論這些消息有沒有被消費。好比,若是消息的保存策略被設置爲2天,那麼在一個消息被髮布的兩天時間內,它都是能夠被消費的,以後它將被丟棄以釋放空間。Kafka的性能是和數據量無關的常量級的,因此保留太多的數據並非問題。緩存

實際上每一個consumer惟一須要維護的數據是消息在日誌中的位置,也就是offset。這個offset有consumer來維護:通常狀況下隨着consumer不斷的讀取消息,這offset的值不斷線性增長,但其實consumer能夠在任何它想要的位置讀取記錄,好比它能夠將offset設置成爲一箇舊的值來重讀以前的消息。服務器

正由於以上的特色,使Kafka consumers很是的輕量級:它們能夠在不對集羣和其餘consumer形成影響的狀況下讀取消息。例如,你可使用命令行工具去"tail"任何主題的內容,而不會對其餘正在消費該消息的consumer形成影響。session

4.Producers

Producer將消息發佈到它指定的topic中,並負責決定發佈到哪一個分區。一般簡單的由負載均衡機制隨機選擇分區,也能夠根據一些更復雜的語義分區算法(好比基於記錄一些鍵值)來完成。使用的更多的是第二種。默認是defaultPartition Utils.abs(key.hashCode) % numPartitions架構

5.Consumers

每一個 Consumer 進程都會劃歸到一個邏輯的Consumer Group中,邏輯的訂閱者是Consumer Group,同一個 Consumer Group 中的 Consumer 能夠在不一樣的程序中,也能夠在不一樣的機器上。因此一條message能夠被多個訂閱該 message 所在的topic的每個Consumer Group 所消費,也就好像是這條message被廣播到每一個Consumer Group同樣。而每一個Consumer Group中,相似於一個Queue(JMS中的Queue)的概念差很少,即topic中的一條message只會被Consumer Group中的一個Consumer消費。

上圖顯示,一個kafka cluster中的某個topic有4個分區(P0-P3)和2個consumer組。A組有2個consumer,B組有4個consumer。

其實上面所說的訂閱關係還不夠明確,其實topic中的partition被分配到某個consumer上,也就是某個consumer訂閱了某個partition。Consumer Group 訂閱的是topic,可是consumer訂閱的是partition,而不是message。因此在同一時間點上,訂閱到同一個partition的consumer必然屬於不一樣的Consumer Group。另外,partition分配的工做是在consumer leader中完成的。

Consumer 與 Consumer Group 的動態維護

當一個Consumer 進程掛掉 或者是卡住時,該Consumer所訂閱的partition會被從新分配到該group內的其它的Consumer上。當一個consumer加入到一個Consumer Group中時,一樣會從其它的Consumer中分配出一個或者多個partition 到這個新加入的Consumer。

當啓動一個Consumer時,會指定它要加入的group,使用的是配置項:group.id。

爲了維持Consumer 與 Consumer Group的關係,須要Consumer週期性的發送heartbeat到coordinator(協調者,在早期版本,以zookeeper做爲協調者。後期版本則以某個broker做爲協調者)。當Consumer因爲某種緣由不能發Heartbeat到coordinator時,而且時間超過session.timeout.ms時,就會認爲該consumer已退出,它所訂閱的partition會分配到同一group 內的其它的consumer上。而這個過程,被稱爲rebalance。

若是一個consumer 進程一直在週期性的發送heartbeat,可是它就是不消費消息,這種狀態稱爲livelock狀態。

Coordinator

Coordinator 協調者,協調consumer、broker。早期版本中Coordinator,使用zookeeper實現,可是這樣作,rebalance的負擔過重。爲了解決scalable的問題,再也不使用zookeeper,而是讓每一個broker來負責一些group的管理,這樣consumer就徹底再也不依賴zookeeper了。

Consumer鏈接到coordinator

從Consumer的實現來看,在執行poll或者是join group以前,都要保證已鏈接到Coordinator。鏈接到coordinator的過程是:

1)鏈接到最後一次鏈接的broker(若是是剛啓動的consumer,則要根據配置中的borker)。它會響應一個包含coordinator信息(host, port等)的response。

2)鏈接到coordinator。

Consumer Group Management

Consumer Group 管理中,也是須要coordinator的參與。一個Consumer要join到一個group中,或者一個consumer退出時,都要進行rebalance。進行rebalance的流程是:

1)會給一個coordinator發起Join請求(請求中要包括本身的一些元數據,例如本身感興趣的topics)

2)Coordinator 根據這些consumer的join請求,選擇出一個leader,並通知給各個consumer。這裏的leader是consumer group 內的leader,是由某個consumer擔任,不要與partition的leader混淆。

3)Consumer leader 根據這些consumer的metadata,從新爲每一個consumer member從新分配partition。分配完畢經過coordinator把最新分配狀況同步給每一個consumer。

4)Consumer拿到最新的分配後,繼續工做。

Kafka如何保證消息的有序性

傳統的隊列在服務器上保存有序的消息,若是多個consumers同時從這個服務器消費消息,服務器就會以消息存儲的順序向consumer分發消息。雖然服務器按順序發佈消息,可是消息是被異步的分發到各consumer上,因此當消息到達時可能已經失去了原來的順序,這意味着併發消費將致使順序錯亂。爲了不故障,這樣的消息系統一般使用「專用consumer」的概念,其實就是隻容許一個消費者消費消息,固然這就意味着失去了併發性。

在這方面Kafka作的更好,經過分區的概念,Kafka能夠在多個consumer組併發的狀況下提供較好的有序性和負載均衡。將每一個分區分只分發給一個consumer組,這樣一個分區就只被這個組的一個consumer消費,就能夠順序的消費這個分區的消息。由於有多個分區,依然能夠在多個consumer組之間進行負載均衡。注意consumer組的數量不能多於分區的數量,也就是有多少分區就容許多少併發消費。

Kafka只能保證一個分區以內消息的有序性,在不一樣的分區之間是不能夠的,這已經能夠知足大部分應用的需求。若是須要topic中全部消息的有序性,那就只能讓這個topic只有一個分區,固然也就只有一個consumer組消費它。

6.Distribution

Producer將消息發佈到它指定的topic中,並負責決定發佈到哪一個分區。一般簡單的由負載均衡機制隨機選擇分區,但也能夠經過特定的分區函數選擇分區。使用的更多的是第二種。默認是defaultPartition Utils.abs(key.hashCode) % numPartitions
每一個分區(partition)在 Kafka 集羣的若干服務中都有副本,這樣這些持有副本的服務能夠共同處理數據和請求,副本數量是能夠配置的(replication-factor 1),副本使Kafka具有了容錯能力。
每個分區都由一個服務器做爲「leader」,零或若干服務器做爲「followers」,leader負責處理消息的讀和寫,與此同時,follower會被動的去複製leader上的數據。
若是leader發生故障,followers中的一臺則會自動成爲leader。每臺服務器能夠做爲一些分區的leader,同時也能夠做爲其餘分區的follower,這樣集羣就會據有較好的負載均衡。特別強調,和mysql中主從有區別,mysql作主從是爲了讀寫分離,在kafka中讀寫操做都是leader。

在Kafka partition中,每一個消息有一個惟一標識,即partition內的offset。每一個consumer group中的訂閱到某個partition的consumer在從partition中讀取數據時,是依次讀取的。

上圖中,Consumer A、B分屬於不用的Consumer Group。Consumer B讀取到offset =11,Consumer A讀取到offset=9 。這個值表示Consumer Group中的某個Consumer 在下次讀取該partition時會從哪一個offset的 message開始讀取,即 Consumer Group A 中的Consumer下次會從offset = 9 的message 讀取, Consumer Group B 中的Consumer下次會從offset = 11 的message 讀取。

這裏並無說是Consumer A 下次會從offset = 9 的message讀取,緣由是Consumer A可能會退出Group ,而後Group A 進行rebalance,即從新分配分區。

Kafka的特色

1.Kafka做爲消息系統

如何將Kafka的流的概念和傳統的企業信息系統做比較?

消息處理模型從來有兩種:隊列和發佈-訂閱。在隊列模型中,一組消費者能夠從服務器讀取記錄,每一個記錄都會被其中一個消費者處理; 在發佈-訂閱模式裏,記錄被廣播到全部的消費者。這兩種模式都具備必定的優勢和弱點。隊列的優勢是它可讓你把數據分配到多個消費者去處理,它可讓您擴展你的處理能力。不幸的是,隊列不支持多個訂閱者,一旦一個進程讀取了數據,這個數據就會消失。發佈-訂閱模式可讓你廣播數據到多個進程,可是由於每個消息發送到每一個訂閱者,沒辦法對訂閱者處理能力進行擴展。

Kafka的消費羣的推廣了這兩個概念。消費羣能夠像隊列同樣讓消息被一組進程處理(消費羣的成員),與發佈 – 訂閱模式同樣,Kafka可讓你發送廣播消息到多個消費羣。

Kafka的模型的優勢是,每一個主題都具備這兩個屬性,它能夠擴展處理能力,也能夠實現多個訂閱者,沒有必要二選一。

Kafka比傳統的消息系統具備更強的消息順序保證的能力。

傳統的消息隊列的消息在隊列中是有序的,多個消費者從隊列中消費消息,服務器按照存儲的順序派發消息。然而,儘管服務器是按照順序派發消息,可是這些消息記錄被異步傳遞給消費者,消費者接收到的消息也許已是亂序的了。這實際上意味着消息的排序在並行消費中都將丟失。消息系統一般靠 「排他性消費」( exclusive consumer)來解決這個問題,只容許一個進程從隊列中消費,固然,這意味着沒有並行處理的能力。

Kafka作的更好。經過一個概念:並行性-分區-主題實現主題內的並行處理,Kafka是可以經過一組消費者的進程同時提供排序保證和負載均衡。每一個主題的分區指定給每一個消費羣中的一個消費者,使每一個分區只由該組中的一個消費者所消費。經過這樣作,咱們確保消費者是一個分區惟一的讀者,從而順序的消費數據。由於有許多的分區,因此負載還可以均衡的分配到不少的消費者實例上去。可是請注意,一個消費羣的消費者實例不能比分區數量多。

2.Kafka做爲存儲系統

任何消息隊列都可以解耦消息的生產和消費,還可以有效地存儲正在傳送的消息。Kafka不同凡響的是,它是一個很是好的存儲系統。

Kafka把消息數據寫到磁盤和備份分區。Kafka容許生產者等待返回確認,直到副本複製和持久化所有完成才認爲成功,不然則認爲寫入服務器失敗。

Kafka使用的磁盤結構很好擴展,Kafka將執行相同的策略無論你是有50 KB或50TB的持久化數據。

因爲存儲的重要性,並容許客戶控制本身的讀取位置,你能夠把Kafka認爲是一種特殊用途的分佈式文件系統,致力於高性能,低延遲的有保障的日誌存儲,可以備份和自我複製。

相關文章
相關標籤/搜索