RocketMQ訊息儲存(一) - mmap零拷貝
RocketMQ訊息儲存(一) - mmap零拷貝(前置篇)
從本篇開始研究Broker 對檔案的儲存, 這些檔案分為三類 (CommitLog , ConsumeQueue , IndexFile) 。
而在分析檔案儲存的原始碼之前, 我們要先了解一個重要的前置知識: 零拷貝IO 技術.
下面是針對不同的開源MQ總結的底層使用的IO方式:
MQ | read/write |
---|---|
RocketMQ | mmap/mmap (預設,可通過修改配置,配置成FileChannel,原因是作者想避免PageCache的鎖競爭,通過兩層架構實現讀寫分離) |
Kafka | record記錄基於sendfile/sendfile index基於mmap/mmap |
ActiveMQ | RandomAccessFile/RandomAccessFile |
1. 基本概念
我們需要先弄清楚, 實體記憶體與虛擬記憶體之間的關係, 以及虛擬記憶體下 使用者空間與核心空間的關係, 弄清楚這些概念後對我們去理解 零拷貝 就非常的簡單。
下面時我從 網上蕩下來的一張圖片:
這個圖片我認為 非常清晰的能夠體現出 上述我說的關係。
-
實體記憶體: 就是實際上計算機真實的記憶體大小。
-
虛擬記憶體:為了解決多程序出現同時操作同一實體記憶體地址的現象,於是就抽象虛擬記憶體。
-
使用者空間/核心空間: 為了系統安全性考慮,使用者程序不能直接操作底層核心,因此就把 虛擬記憶體 又劃分出了 使用者空間 、核心空間兩部分。
-
對映:
上面這一張圖是 虛擬記憶體 對映到 實體記憶體。
多程序的虛擬記憶體中的核心空間是共享的,都對映在實體記憶體的系統核心空間上。 而虛擬記憶體中的使用者空間 則被對映到了不同的實體記憶體區域。
2. mmap記憶體對映原理分析
以上我們清楚了 實體記憶體與虛擬記憶體之間的對映關係, 它們之間實際上是通過 頁表和MMU的方式來實現 地址之間的轉換對映。
而本小節所說的 mmap記憶體對映 中的 對映 主要指的是 硬碟上檔案的位置 與 **虛擬記憶體地址空間 **的 一 一對應,這種關係是邏輯上的概念。
注意: 在mmap的記憶體對映過程中, 並沒有實際的資料拷貝,檔案也並沒有載入實體記憶體,只是邏輯上與虛擬記憶體形成了對映關係。
過程1: 實際上就是mmap記憶體對映, 只是建立了 檔案 與 虛擬記憶體之間 邏輯上的對映關係。
假設 這時候 需要 讀取檔案上的一段資料, 因為 虛擬記憶體 與 檔案的位置 已經建立了邏輯上的對映關係, 一次直接通過 虛擬記憶體來從實體記憶體上獲取資料。
過程2:通過虛擬記憶體地址與實體記憶體地址的轉換, 能夠訪問到 目標那塊地址 上有無資料。 若沒有資料,則說明檔案沒有載入到實體記憶體中,因此會產生缺頁中斷。
過程3:產生了缺頁中斷,因此就需要實體記憶體的核心去完成資料拷貝。 也就是將檔案的資料 載入到 對應的實體記憶體地址中。
過程4:若在載入資料到實體記憶體的過程中, 實體記憶體的空間不夠用, 因此就會產生 swap 交換, 從實體記憶體上騰出一部分空間給檔案資料使用。