1. 程式人生 > 其它 >Kafka:大白話講解 kafka 架構原理 ( 轉載 )

Kafka:大白話講解 kafka 架構原理 ( 轉載 )

前言

本文轉載至 https://blog.csdn.net/yuanlong122716/article/details/104825604 

大家可以多多關注此文章博主,此博主釋出的文章質量都很不錯,本文只是抄錄一份方便自己學習。

一、kafka簡介

Kafka最初由Linkedin公司開發,是一個分散式的、分割槽的、多副本的、多訂閱者,基於zookeeper協調的分散式日誌系統(也可以當做MQ系統),常用於web/nginx日誌、訪問日誌、訊息服務等等,Linkedin於2010年貢獻給了Apache基金會併成為頂級開源專案。

二、kafka的特性

  • 高吞吐量、低延遲:  kafka每秒可以處理幾十萬條訊息,它的延遲最低只有幾毫秒;
  • 可擴充套件性:                kafka叢集支援熱擴充套件;
  • 永續性、可靠性:     訊息被持久化到本地磁碟,並且支援資料備份防止丟失;
  • 容錯性:                   允許叢集中的節點失敗(若副本數量為n,則允許n-1個節點失敗);
  • 高併發:                   單機可支援數千個客戶端同時讀寫;

三、kafka的應用場景

  • 日誌收集:       一個公司可以用Kafka收集各種服務的log,通過kafka以統一介面開放給各種消費端,例如hadoop、Hbase、Solr等。
  • 訊息系統:       解耦生產者和消費者、快取訊息等。
  • 使用者活動跟蹤:Kafka經常被用來記錄web使用者或者app使用者的各種活動,如瀏覽網頁、搜尋記錄、點選等活動,這些活動資訊被各個伺服器釋出到kafka的topic中,然後訂閱者通過訂閱這些topic來做實時的監控分析,或者裝載到hadoop、資料倉庫中做離線分析和挖掘。
  • 運營指標:       Kafka也經常用來記錄運營監控資料。
  • 流式處理

四、kafka架構( 重點 )

先介紹下Kafka中非常重要的術語。下面是一個kafka架構圖:

 kafka架構中包含四大元件:生產者、消費者、kafka叢集、zookeeper叢集

1、broker

kafka 叢集包含一個或多個伺服器,每個伺服器節點稱為一個broker。

2、topic

每條釋出到kafka叢集的訊息都有一個類別,這個類別稱為topic,其實就是將訊息按照topic來分類,topic是邏輯上的分類,同一個topic的資料既可以在同一個broker上也可以在不同的broker結點上。

3、partition

分割槽,每個topic被物理劃分為一個或多個分割槽,每個分割槽在物理上對應一個資料夾,該資料夾裡面儲存了這個分割槽的所有訊息和索引檔案。在建立topic時可指定parition數量,生產者將訊息傳送到topic時,訊息會根據 分割槽策略 追加到分割槽檔案的末尾,屬於順序寫磁碟,因此效率非常高(經驗證,順序寫磁碟效率比隨機寫記憶體還要高,這是Kafka高吞吐率的一個很重要的保證)。

 

上面提到了分割槽策略,所謂分割槽策略就是決定生產者將訊息傳送到哪個分割槽的演算法。Kafka 為我們提供了預設的分割槽策略,同時它也支援自定義分割槽策略。kafka允許為每條訊息設定一個key,一旦訊息被定義了 Key,那麼就可以保證同一個 Key 的所有訊息都進入到相同的分割槽,這種策略屬於自定義策略的一種,被稱作"按訊息key儲存策略",或Key-ordering 策略。

同一topic的多個分割槽可以部署在多個機器上,以此來實現 kafka 的伸縮性。同一partition中的資料是有序的,但topic下的多個partition之間在消費資料時不能保證有序性,在需要嚴格保證訊息順序消費的場景下,可以將partition數設為1,但這種做法的缺點是降低了吞吐,一般來說,只需要保證每個分割槽的有序性,再對訊息設定key來保證相同key的訊息落入同一分割槽,就可以滿足絕大多數的應用。

4、offset

partition中的每條訊息都被標記了一個序號,這個序號表示訊息在partition中的偏移量,稱為offset,每一條訊息在partition都有唯一的offset,訊息者通過指定offset來指定要消費的訊息。

正常情況下,消費者在消費完一條訊息後會遞增offset,準備去消費下一條訊息,但也可以將offset設成一個較小的值,重新消費一些消費過的訊息,可見offset是由consumer控制的,consumer想消費哪一條訊息就消費哪一條訊息,所以kafka broker是無狀態的,它不需要標記哪些訊息被消費過。

5、producer

生產者,生產者傳送訊息到指定的topic下,訊息再根據分配規則append到某個partition的末尾。

6、consumer

消費者,消費者從topic中消費資料。

7、consumer group

消費組,每個consumer屬於一個特定的consumer group,可以通過consumer.propertise檔案中的group.id屬性指定,如果不指定,預設是"test-consumer-group"。

一個consumer可以消費多個partition,但是同一個partition只能被同一個consumer group裡面的一個consumer消費。一個consumer佔用該partition的消費後,本消費組中的其他消費者將不能再消費,但其他消費組的消費者仍然可以消費。

這也是kafka用來實現訊息的廣播和單播的手段,如果需要實現廣播,一個consumer group內只放一個消費者即可,要實現單播,將所有的消費者放到同一個consumer group即可。

8、leader

每個partition有多個副本,其中有且僅有一個作為leader,leader會負責所有的客戶端讀寫操作。

9、follower

follower不對外提供服務,只與leader保持資料同步,如果leader失效,則選舉一個follower來充當新的leader。當follower與leader掛掉、卡住或者同步太慢,leader會把這個follower從ISR列表中刪除,重新建立一個follower。

解釋一下ISR:簡單來說,分割槽的所有副本(這裡所說的副本包括leader和follower)統稱為 AR (Assigned Replicas)。所有與leader副本保持一定程度同步的副本(包括leader副本在內)組成 ISR (In Sync Replicas)。生產者傳送訊息時,訊息會先發送到leader副本,然後follower副本才能從leader中拉取訊息進行同步,同步期間,follow副本相對於leader副本而言會有一定程度的滯後,前面所說的"一定程度同步"就是指可忍受的滯後範圍,這個範圍可以通過引數進行配置。於leader副本同步滯後過多的副本(不包括leader副本)將組成 OSR (Out-of-Sync Replied)。

由此可見,AR = ISR + OSR,理想情況下,所有的follower副本都應該與leader 副本保持一定程度的同步,即AR=ISR,OSR集合為空。

10、rebalance

同一個consumer group下的多個消費者互相協調消費工作,我們這樣想,一個topic分為多個分割槽,一個consumer group裡面的所有消費者合作,一起去消費所訂閱的某個topic下的所有分割槽(每個消費者消費部分分割槽),kafka會將該topic下的所有分割槽均勻的分配給consumer group下的每個消費者,如下圖,

 

Rebalance表示"重平衡",consumer group內某個消費者掛掉後,其他消費者自動重新分配訂閱主題分割槽的過程,是 Kafka 消費者端實現高可用的重要手段。如下圖Consumer Group A中的C2掛掉,C1會接收P1和P2,以達到重新平衡。同樣的,當有新消費者加入consumer group,也會觸發重平衡操作。

五、對kafka架構的幾點解釋

1、一個典型的kafka叢集中包含若干producer,若干broker(Kafka支援水平擴充套件,一般broker數量越多,叢集吞吐率越高),若干consumer group,以及一個zookeeper叢集。kafka通過zookeeper協調管理kafka叢集,選舉分割槽leader,以及在consumer group發生變化時進行rebalance。

2、kafka的topic被劃分為一個或多個分割槽,多個分割槽可以分佈在一個或多個broker節點上,同時為了故障容錯,每個分割槽都會複製多個副本,分別位於不同的broker節點,這些分割槽副本中(不管是leader還是follower都稱為分割槽副本),一個分割槽副本會作為leader,其餘的分割槽副本作為follower。

leader負責所有的客戶端讀寫操作,follower不對外提供服務,僅僅從leader上同步資料,當leader出現故障時,其中的一個follower會頂替成為leader,繼續對外提供服務。

3、對於傳統的MQ而言,已經被消費的訊息會從佇列中刪除,但在Kafka中被消費的訊息也不會立馬刪除,在kafka的server.propertise配置檔案中定義了資料的儲存時間,當檔案到設定的儲存時間時才會刪除。

# 資料的儲存時間(單位:小時,預設為7天)
 
log.retention.hours=168

因為Kafka讀取訊息的時間複雜度為O(1),與檔案大小無關,所以這裡刪除過期檔案與提高Kafka效能並沒有關係,所以選擇怎樣的刪除策略應該考慮磁碟以及具體的需求。

4、點對點模式 VS 釋出訂閱模式

傳統的訊息系統中,有兩種主要的訊息傳遞模式:點對點模式、釋出訂閱模式。

①點對點模式

生產者傳送訊息到queue中,queue支援存在多個消費者,但是對一個訊息而言,只可以被一個消費者消費,並且在點對點模式中,已經消費過的訊息會從queue中刪除不再儲存。

②釋出訂閱模式

生產者將訊息釋出到topic中,topic可以被多個消費者訂閱,且釋出到topic的訊息會被所有訂閱者消費。而kafka就是一種釋出訂閱模式。

5、消費端 PULL和PUSH

①Push方式:由訊息中介軟體主動地將訊息推送給消費者;

②Pull方式:由消費者主動向訊息中介軟體拉取訊息;

六、kafka和rabbitMQ對比

七、kafka的吞吐量為什麼這麼高?

1、順序讀寫磁碟

Kafka是將訊息持久化到本地磁碟中的,一般人會認為磁碟讀寫效能差,可能會對Kafka效能提出質疑。實際上不管是記憶體還是磁碟,快或慢的關鍵在於定址方式,磁碟分為順序讀寫與隨機讀寫,記憶體一樣也分為順序讀寫與隨機讀寫。基於磁碟的隨機讀寫確實很慢,但基於磁碟的順序讀寫效能卻很高,一般而言要高出磁碟的隨機讀寫三個數量級,一些情況下磁碟順序讀寫效能甚至要高於記憶體隨機讀寫,這裡給出著名學術期刊 ACM Queue 上的一張效能對比圖:

2、page cache

為了優化讀寫效能,Kafka利用了作業系統本身的Page Cache,就是利用作業系統自身的記憶體而不是JVM空間記憶體。這樣做是因為,

> JVM中一切皆物件,物件的儲存會帶來額外的記憶體消耗;

> 使用JVM會受到GC的影響,隨著資料的增多,垃圾回收也會變得複雜與緩慢,降低吞吐量;

另外作業系統本身對page cache做了大量優化,通過作業系統的Page Cache,Kafka的讀寫操作基本上是基於系統記憶體的,讀寫效能也得到了極大的提升。

3、零拷貝

零拷貝是指Kafka利用 linux 作業系統的 "zero-copy" 機制在消費端做的優化。首先來看一下消費端在消費資料時,資料從broker磁碟通過網路傳輸到消費端的整個過程:

> 作業系統從磁碟讀取資料到核心空間(kernel space)的page cache;

> 應用程式讀取page cache的資料到使用者空間(user space)的緩衝區;

> 應用程式將使用者空間緩衝區的資料寫回核心空間的socket緩衝區(socket buffer);

> 作業系統將資料從socket緩衝區複製到硬體(如網絡卡)緩衝區;

整個過程如上圖所示,這個過程包含4次copy操作和2次系統上下文切換,而上下文切換是CPU密集型的工作,資料拷貝是I/O密集型的工作,效能其實非常低效。零拷貝就是使用了一個名為sendfile()的系統呼叫方法,將資料從page cache直接傳送到Socket緩衝區,避免了系統上下文的切換,消除了從核心空間到使用者空間的來回複製。從上圖可以看出,"零拷貝"並不是說整個過程完全不發生拷貝,而是站在核心的角度來說的,避免了核心空間到使用者空間的來回拷貝。

4、分割槽分段

Kafka的message是按topic分類儲存的,topic中的資料又是按照一個一個的partition即分割槽儲存到不同broker節點。每個partition對應了作業系統上的一個資料夾,partition實際上又是按照segment分段儲存的。這也非常符合分散式系統分割槽分桶的設計思想。

通過這種分割槽分段的設計,Kafka的message訊息實際上是分散式儲存在一個一個小的segment中的,每次檔案操作也是直接操作的segment。為了進一步的查詢優化,Kafka又預設為分段後的資料檔案建立了索引檔案,就是檔案系統上的.index檔案。這種分割槽分段+索引的設計,不僅提升了資料讀取的效率,同時也提高了資料操作的並行度。

總之,Kafka採用順序讀寫、Page Cache、零拷貝以及分割槽分段等這些設計,再加上在索引方面做的優化,另外Kafka資料讀寫也是批量的而不是單條的,使得Kafka具有了高效能、高吞吐、低延時的特點。

 

文章轉載至:https://blog.csdn.net/yuanlong122716/article/details/104825604