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

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

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章