Kafka 對消息的存儲和緩存嚴重依賴於文件系統。人們對於「磁盤速度慢」的廣泛印象,使得人們對於持久化的架構可以提供強有力的性能產生懷疑。事實上,磁盤的速度比人們預期的要慢的多,也快得多,這取決於人們使用磁盤的方式。並且設計合理的磁盤結構一般能夠和網絡同樣快。linux
關於磁盤性能的關鍵事實是,磁盤的吞吐量和過去十年裏磁盤的尋址延遲不一樣。所以,使用6個7200rpm、SATA接口、RAID-5的磁盤陣列在JBOD配置下的順序寫入的性能約爲600MB/秒,但隨機寫入的性能僅約爲100k/秒,相差6000倍以上。由於線性的讀取和寫入是磁盤使用模式中最有規律的,而且由操做系統進行了大量的優化。現代操做系統提供了 read-ahead 和 write-behind 技術,read-ahead 是以大的 data block 爲單位預先讀取數據,而 write-behind 是將多個小型的邏輯寫合併成一次大型的物理磁盤寫入。關於該問題的進一步討論能夠參考 ACM Queue article,他們發現實際上 順序磁盤訪問在某些狀況下比隨機內存訪問還要快apache
低效率的操做是字節拷貝,在消息量少時,這不是什麼問題。可是在高負載的狀況下,影響就不容忽視。爲了不這種狀況,咱們使用 producer ,broker 和 consumer 都共享的標準化的二進制消息格式,這樣數據塊不用修改就能在他們之間傳遞。緩存
broker 維護的消息日誌自己就是一個文件目錄,每一個文件都由一系列以相同格式寫入到磁盤的消息集合組成,這種寫入格式被 producer 和 consumer 共用。保持這種通用格式能夠對一些很重要的操做進行優化: 持久化日誌塊的網絡傳輸。 現代的unix 操做系統提供了一個高度優化的編碼方式,用於將數據從 pagecache 轉移到 socket 網絡鏈接中;在 Linux 中系統調用 sendfile 作到這一點。安全
爲了理解 sendfile 的意義,瞭解數據從文件到套接字的常見數據傳輸路徑就很是重要:服務器
咱們指望一個廣泛的應用場景,一個 topic 被多消費者消費。使用上面提交的 zero-copy(零拷貝)優化,數據在使用時只會被複制到 pagecache 中一次(經過DMA複製),節省了每次拷貝到用戶空間內存中,再從用戶空間進行讀取的消耗。這使得消息可以以接近網絡鏈接速度的 上限進行消費。網絡
pagecache 和 sendfile 的組合使用意味着,在一個kafka集羣中,大多數 consumer 消費時,您將看不到磁盤上的讀取活動,由於數據將徹底由緩存提供。架構
JAVA 中更多有關 sendfile 方法和 zero-copy (零拷貝)相關的資料,能夠參考這裏的文章app
page cache,又稱pcache,其中文名稱爲頁高速緩衝存儲器,簡稱頁高緩。page cache的大小爲一頁,一般爲4K。在linux讀寫文件時,它用於緩存文件的邏輯內容,從而加快對磁盤上映像和數據的訪問,以此來減小對磁盤I/O的操做。socket
DMA(Direct Memory Access)原理: 讀一個磁盤扇區,CPU可能發出三個存儲指令發起磁盤讀,第一個指令發送一個命令字,告訴磁盤發起一個讀同時還發送了其餘參數。第二個參數指明瞭應該讀的邏輯塊號,第三個指令指明瞭應該存儲磁盤扇區內容的主存地址。 在磁盤控制器收到來自CPU的讀命令後,它將邏輯塊號翻譯成一個扇區地址,讀取扇區的內容,而後將這些內容直接傳到主存,不須要CPU的干涉。DMA傳送完成,磁盤扇區的內存被安全的存儲在主存中之後,磁盤控制器經過給CPU發送一箇中斷信號來通知CPU。性能
參考書籍:《深刻理解計算機系統》
Kafka 以高效的批處理格式支持一批消息能夠壓縮在一塊兒發送到服務器。這批消息將以壓縮格式寫入,而且在日誌中保持壓縮,只會在 consumer 消費時解壓縮。 Kafka 支持 GZIP,Snappy 和 LZ4 壓縮協議