雖然kafka的sdk提供了單條訊息傳送,但實際上,kafka 的客戶端 sdk 在實現訊息傳送邏輯的時候,採用了非同步批量傳送的機制;
當你呼叫 send() 方法傳送一條訊息之後,無論你是同步傳送還是非同步傳送,kafka 都不會立即就把這條訊息傳送出去。它會先把這條訊息,存放在記憶體中快取起來,然後選擇合適的時機把快取中的所有訊息組成一批,一次性發給 broker
在 kafka 的服務端批訊息都不會被解開,一直是作為一條「批訊息」來進行處理的
在消費時,訊息同樣是以批為單位進行傳遞的,consumer 從 broker 拉到一批訊息後,在客戶端把批訊息解開,再一條一條交給使用者**處理
順序讀寫相比隨機讀寫省去了大部分的定址時間,它只要定址一次,就可以連續地讀寫下去,所以說,效能要比隨機讀寫要好很多
kafka 就是充分利用了磁碟的這個特性。它的儲存設計非常簡單,對於每個分割槽,它把從 producer 收到的訊息,順序地寫入對應的 log 檔案中,乙個檔案寫滿了,就開啟乙個新的檔案這樣順序寫下去。消費的時候,也是從某個全域性的位置開始,也就是某乙個 log 檔案中的某個位置開始,順序地把訊息讀出來
pagecache
pagecache 是現代作業系統都具有的一項基本特性。通俗地說,pagecache 就是作業系統在記憶體中給磁碟上的檔案建立的快取。無論我們使用什麼語言編寫的程式,在呼叫系統的 api 讀寫檔案的時候,並不會直接去讀寫磁碟上的檔案,應用程式實際操作的都是 pagecache,也就是檔案在記憶體中快取的副本。應用程式寫入檔案
作業系統會先把資料寫入到記憶體中的 pagecache,然後再一批一批地寫到磁碟上應用程式讀取檔案
有兩種情況:一種是 pagecache 中有資料,那就直接讀取;另一種情況是,pagecache 中沒有資料,這時候作業系統會引發乙個缺頁中斷,應用程式的讀取執行緒會被阻塞,作業系統把資料從檔案中複製到 pagecache 中,然後應用程式再從 pagecache 中繼續把資料讀出來,這時會真正讀一次磁碟上的檔案,這個讀的過程就會比較慢。pagecache清理機制
使用者的應用程式在使用完某塊 pagecache 後,作業系統並不會立刻就清除這個 pagecache,而是盡可能地利用空閒的物理記憶體儲存這些 pagecache,除非系統記憶體不夠用,作業系統才會清理掉一部分 pagecache。清理的策略一般是 lru 或它的變種演算法,它保留 pagecache 的邏輯是:優先保留最近一段時間最常使用的那些 pagecachekafka讀寫訊息檔案
kafka充分利用了 pagecache 的特性。一般來說,訊息剛剛寫入到服務端就會被消費,按照 lru 的「優先清除最近最少使用的頁」這種策略,讀取的時候,對於這種剛剛寫入的 pagecache,命中的機率會非常高。也就是說,大部分情況下,kafka消費讀訊息都會命中 pagecache,帶來的好處有兩個:乙個是讀取的速度會非常快,另外乙個是,給寫入訊息讓出磁碟的 io 資源,間接也提公升了寫入的效能。在訊息服務端處理消費的大致過程:
這個過程中,資料實際上做了 2 次或者 3 次複製:
kafka 使用零拷貝技術可以把這個複製次數減少一次,上面的 2、3 步驟兩次複製合併成一次複製。直接從 pagecache 中把資料複製到 socket 緩衝區中,這樣不僅減少一次資料複製,更重要的是,由於不用把資料複製到使用者記憶體空間,dma 控制器可以直接完成資料複製,不需要 cpu 參與,速度更快
Kafka如何實現高效能IO?
雖然kafka的sdk提供了單條訊息傳送,但實際上,kafka 的客戶端 sdk 在實現訊息傳送邏輯的時候,採用了非同步批量傳送的機制 當你呼叫 send 方法傳送一條訊息之後,無論你是同步傳送還是非同步傳送,kafka 都不會立即就把這條訊息傳送出去。它會先把這條訊息,存放在記憶體中快取起來,然後...
訊息佇列選型 Kafka 如何實現高效能?
訊息佇列中應用最廣泛的 kafka 和 rocketmq 不知道你有沒有了解過自己電腦的配置?我們一般會認為高效能是和高配置聯絡在一起的,比如大記憶體比小記憶體快,8 核的機器比 4 核的機器快。我身邊也有一些朋友是攢機愛好者,對各種硬體配置如數家珍。對於伺服器來說,家用電腦的效能與配置的關係也同樣...
Redis 高效能IO模型
redis核心結束與實戰 03 通常說redis 是單執行緒,主要是指 redis 的網路 io 和鍵值對讀寫是由乙個執行緒來完成的,這也是 redis 對外提供鍵值儲存服務的主要流程。但 redis 的其他功能,比如持久化 非同步刪除 集群資料同步等,其實是由額外的執行緒執行的。目錄 一 多執行緒...