'基於磁盤的Kafka為什麼這麼快'

"

專注於Java領域優質技術,歡迎關注

作者: Wyman 大數據手稿筆記

Kafka是大數據領域無處不在的消息中間件,目前廣泛使用在企業內部的實時數據管道,並幫助企業構建自己的流計算應用程序。Kafka雖然是基於磁盤做的數據存儲,但卻具有高性能、高吞吐、低延時的特點,其吞吐量動輒幾萬、幾十上百萬,這其中的原由值得我們一探究竟。本文屬於Kafka知識掃盲系列,讓我們一起掌握Kafka各種精巧的設計。

順序讀寫

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


"

專注於Java領域優質技術,歡迎關注

作者: Wyman 大數據手稿筆記

Kafka是大數據領域無處不在的消息中間件,目前廣泛使用在企業內部的實時數據管道,並幫助企業構建自己的流計算應用程序。Kafka雖然是基於磁盤做的數據存儲,但卻具有高性能、高吞吐、低延時的特點,其吞吐量動輒幾萬、幾十上百萬,這其中的原由值得我們一探究竟。本文屬於Kafka知識掃盲系列,讓我們一起掌握Kafka各種精巧的設計。

順序讀寫

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


基於磁盤的Kafka為什麼這麼快


磁盤的順序讀寫是磁盤使用模式中最有規律的,並且操作系統也對這種模式做了大量優化,Kafka就是使用了磁盤順序讀寫來提升的性能。Kafka的message是不斷追加到本地磁盤文件末尾的,而不是隨機的寫入,這使得Kafka寫入吞吐量得到了顯著提升。

Page Cache

為了優化讀寫性能,Kafka利用了操作系統本身的Page Cache,就是利用操作系統自身的內存而不是JVM空間內存。這樣做的好處有:

  • 避免Object消耗:如果是使用Java堆,Java對象的內存消耗比較大,通常是所存儲數據的兩倍甚至更多。
  • 避免GC問題:隨著JVM中數據不斷增多,垃圾回收將會變得複雜與緩慢,使用系統緩存就不會存在GC問題。

相比於使用JVM或in-memory cache等數據結構,利用操作系統的Page Cache更加簡單可靠。首先,操作系統層面的緩存利用率會更高,因為存儲的都是緊湊的字節結構而不是獨立的對象。其次,操作系統本身也對於Page Cache做了大量優化,提供了write-behind、read-ahead以及flush等多種機制。再者,即使服務進程重啟,系統緩存依然不會消失,避免了in-process cache重建緩存的過程。

通過操作系統的Page Cache,Kafka的讀寫操作基本上是基於內存的,讀寫速度得到了極大的提升。

零拷貝

這裡主要講的是Kafka利用linux操作系統的 "零拷貝(zero-copy)" 機制在消費端做的優化。首先來了解下數據從文件發送到socket網絡連接中的常規傳輸路徑:

  • 操作系統從磁盤讀取數據到內核空間(kernel space)的Page Cache
  • 應用程序讀取Page Cache的數據到用戶空間(user space)的緩衝區
  • 應用程序將用戶空間緩衝區的數據寫回內核空間到socket緩衝區(socket buffer)
  • 操作系統將數據從socket緩衝區複製到網絡發送的NIC緩衝區

這個過程包含4次copy操作和2次系統上下文切換,性能其實非常低效。linux操作系統 "零拷貝" 機制使用了sendfile方法,允許操作系統將數據從Page Cache 直接發送到網絡,只需要最後一步的copy操作將數據複製到 NIC 緩衝區,這樣避免重新複製數據。示意圖如下:


"

專注於Java領域優質技術,歡迎關注

作者: Wyman 大數據手稿筆記

Kafka是大數據領域無處不在的消息中間件,目前廣泛使用在企業內部的實時數據管道,並幫助企業構建自己的流計算應用程序。Kafka雖然是基於磁盤做的數據存儲,但卻具有高性能、高吞吐、低延時的特點,其吞吐量動輒幾萬、幾十上百萬,這其中的原由值得我們一探究竟。本文屬於Kafka知識掃盲系列,讓我們一起掌握Kafka各種精巧的設計。

順序讀寫

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


基於磁盤的Kafka為什麼這麼快


磁盤的順序讀寫是磁盤使用模式中最有規律的,並且操作系統也對這種模式做了大量優化,Kafka就是使用了磁盤順序讀寫來提升的性能。Kafka的message是不斷追加到本地磁盤文件末尾的,而不是隨機的寫入,這使得Kafka寫入吞吐量得到了顯著提升。

Page Cache

為了優化讀寫性能,Kafka利用了操作系統本身的Page Cache,就是利用操作系統自身的內存而不是JVM空間內存。這樣做的好處有:

  • 避免Object消耗:如果是使用Java堆,Java對象的內存消耗比較大,通常是所存儲數據的兩倍甚至更多。
  • 避免GC問題:隨著JVM中數據不斷增多,垃圾回收將會變得複雜與緩慢,使用系統緩存就不會存在GC問題。

相比於使用JVM或in-memory cache等數據結構,利用操作系統的Page Cache更加簡單可靠。首先,操作系統層面的緩存利用率會更高,因為存儲的都是緊湊的字節結構而不是獨立的對象。其次,操作系統本身也對於Page Cache做了大量優化,提供了write-behind、read-ahead以及flush等多種機制。再者,即使服務進程重啟,系統緩存依然不會消失,避免了in-process cache重建緩存的過程。

通過操作系統的Page Cache,Kafka的讀寫操作基本上是基於內存的,讀寫速度得到了極大的提升。

零拷貝

這裡主要講的是Kafka利用linux操作系統的 "零拷貝(zero-copy)" 機制在消費端做的優化。首先來了解下數據從文件發送到socket網絡連接中的常規傳輸路徑:

  • 操作系統從磁盤讀取數據到內核空間(kernel space)的Page Cache
  • 應用程序讀取Page Cache的數據到用戶空間(user space)的緩衝區
  • 應用程序將用戶空間緩衝區的數據寫回內核空間到socket緩衝區(socket buffer)
  • 操作系統將數據從socket緩衝區複製到網絡發送的NIC緩衝區

這個過程包含4次copy操作和2次系統上下文切換,性能其實非常低效。linux操作系統 "零拷貝" 機制使用了sendfile方法,允許操作系統將數據從Page Cache 直接發送到網絡,只需要最後一步的copy操作將數據複製到 NIC 緩衝區,這樣避免重新複製數據。示意圖如下:


基於磁盤的Kafka為什麼這麼快


通過這種 "零拷貝" 的機制,Page Cache 結合 sendfile 方法,Kafka消費端的性能也大幅提升。這也是為什麼有時候消費端在不斷消費數據時,我們並沒有看到磁盤io比較高,此刻正是操作系統緩存在提供數據。

分區分段

Kafka的message是按topic分類存儲的,topic中的數據又是按照一個一個的partition即分區存儲到不同broker節點。每個partition對應了操作系統上的一個文件夾,partition實際上又是按照segment分段存儲的。這也非常符合分佈式系統分區分桶的設計思想。

通過這種分區分段的設計,Kafka的message消息實際上是分佈式存儲在一個一個小的segment中的,每次文件操作也是直接操作的segment。為了進一步的查詢優化,Kafka又默認為分段後的數據文件建立了索引文件,就是文件系統上的.index文件。這種分區分段+索引的設計,不僅提升了數據讀取的效率,同時也提高了數據操作的並行度。

總 結

總結起來,Kafka採用順序讀寫、Page Cache、零拷貝以及分區分段等這些設計,再加上在索引方面做的優化,另外Kafka數據讀寫也是批量的而不是單條的,使得Kafka具有了高性能、高吞吐、低延時的特點。這樣,Kafka提供大容量的磁盤存儲也變成了一種優點。由於本人才粗學淺,表述有誤的地方歡迎指教。

"

相關推薦

推薦中...