kafka詳解(二)–kafka為什麼快

前言

Kafka 有多快呢?我們可以使用 OpenMessaging Benchmark Framework 測試框架方便地對 RocketMQ、Pulsar、Kafka、RabbitMQ 等消息系統進行對比測試,因為暫時沒有測試條件(後續補上),我直接用這篇文章的測試結果(Benchmarking Kafka vs. Pulsar vs. RabbitMQ: Which is Fastest?),可以看到,在某種條件下,Kafka 寫入速度比 RabbitMQ 快 15 倍,比 Pulsar 快 2 倍,在最高吞吐量下仍保持低延遲。

throughput-and-latency-quantiles

那麼,為什麼 Kafka 可以那麼快呢?這裡我先簡單總結,後面會展開分析。

  1. 從磁碟中順序讀寫 event
  2. 通過批處理減少大量小 I/O
  3. 從文件到 socket 之間數據零拷貝
  4. 基於分區的橫向擴展

ps:[本系列](部落格後台 – 部落格園 (cnblogs.com))部落格將持續更新。

順序讀寫磁碟

Kafka 嚴重依賴文件系統來讀寫 event。我們不禁會問,磁碟不是很慢嗎?Kafka 真的能提供很好的性能嗎?

事實上,磁碟比人們預期的要慢得多,也快得多,這取決於它們的使用方式。在這篇文章中(ACM Queue article)可以發現,在某些情況下,順序磁碟訪問可能比隨機記憶體訪問更快。這要得益於現代作業系統對磁碟讀寫進行的大量的優化,包括 read-ahead 和 write-behind 技術,當我們順序讀取磁碟時,更多時候訪問的不是磁碟,而是記憶體–pagecache。

jacobs3.jpg

因此,只要順序訪問文件系統,磁碟也可以很快。Kafka 的 event 組織方式以及應用場景,天然地支援了順序讀寫,並且 Kafka 也為此做了許多努力,例如批處理、追加寫入等。

此外,相比主動將 event 維護在記憶體,採用文件系統還有以下好處:

  1. 可以快取更多的數據。在 JVM 中,維護對象的記憶體開銷將是實際數據大小的兩倍甚至更糟,隨著堆內數據的增加,gc 將愈發頻繁。而使用文件系統可以在 pagecache 中快取更多更緊湊的數據,而不需要考慮 gc 問題。

  2. 重啟後恢復更快。由於數據快取在 pagecache,進程重啟,這部分快取仍然可以保持 warn 的狀態,如果在進程記憶體中維護這些數據的話,每次啟動都需要重建(對於 10GB 快取可能需要 10 分鐘)。

  3. 數據不會丟失。如果數據維護在記憶體中,需要考慮定期將數據持久化到磁碟,一致性和性能的權衡將是一個比較麻煩的問題,即便如此,我們也不能保證數據不會丟失,例如 redis 可能損失幾秒的數據,甚至更多。在理論上,Kafka 就不會出現數據丟失的情況。

  4. 大大簡化了程式碼。用於維護快取和文件系統之間一致性的所有邏輯現在都在作業系統中,而作業系統往往更高效、更正確。

通過批處理減少小I/O

小 I/O 操作發生在客戶端和服務端之間的數據傳輸以及服務端自身的持久化操作。

為了避免小 I/O 操作,Kafka 是以批的形式來操作 event,而不是一次發送一條消息。producer 會嘗試在記憶體中積累數據,並在單個請求中發送更大的批,當然,這種方式是犧牲少量額外延遲以獲得更好的吞吐量,我們可以配置累積數量和等待時間來平衡。同理,consumer 讀取數據時也會嘗試一次讀取更多。

批處理可以產生較大順序磁碟操作和連續記憶體塊,不過也產生了較大的網路數據包,相應地,Kafaka 會將消息壓縮後發送,當消息寫入日誌時仍然是壓縮形式,僅由使用者解壓縮。

數據零拷貝

另一個問題是過多的位元組複製。//zzs001

一般情況下,數據從文件傳輸到 socket 的數據路徑為:磁碟 -》內核的 pagecache -》用戶空間緩衝區 -》內核的 socket 緩衝區 -》NIC 緩衝區。

figure1.gif

顯然,這是非常低效的,有四個副本和兩個系統調用。Kafka 使用 sendfile,允許作業系統將數據從 pagecache 直接發送到網路,即磁碟 -》內核的 pagecache-》NIC 緩衝區。從而避免這種重複複製和系統調用。更多關於 sendfile 的內容可以參考Efficient data transfer through zero copy

figure5.gif

需要注意的是,由於 TLS/SSL 庫是工作在用戶空間的,所以,當啟用了 SSL,sendfile 將不能使用。

基於分區的橫向擴展

關於這一點,在上一篇部落格中其實已經提到過。首先,一個 topic 會劃分成一個或多個 partition,這些 partition 一般分布在不同的 broker 實例。producer 發布的 event 會根據某種策略分配到不同的 partition,這樣做的好處是,consumer 可以同時從多台 broker 讀取 event,從而大大提高吞吐量。另外,為了高可用,同一個 partition 還會有多個副本,它們分布在不同的 broker 實例,和很多傳統的消息系統不同,Kafka 的副本是可讀的,即 consumer 不僅可以從主 partition 讀取 event,也可以從副本讀取。//zzs001

zzs_kafka_fast_01

結語

以上內容是最近學習 Kafka 的一些思考和總結(主要參考官方文檔),如有錯誤,歡迎指正。

任何的事物,都可以被更簡單、更連貫、更系統地了解。希望我的文章能夠幫到你。

最後,感謝閱讀。

參考資料

Apache Kafka 官方文檔

Benchmarking Kafka vs. Pulsar vs. RabbitMQ: Which is Fastest?

The OpenMessaging Benchmark Framework

The Pathologies of Big Data – ACM Queue

Efficient data transfer through zero copy – IBM Developer

相關源碼請移步://github.com/ZhangZiSheng001/kafka-demo

本文為原創文章,轉載請附上原文出處鏈接://www.cnblogs.com/ZhangZiSheng001/p/16788561.html

Tags: