快取¶
簡介¶
dm-cache 是由 Joe Thornber、Heinz Mauelshagen 和 Mike Snitzer 編寫的一個裝置對映器目標。
它旨在透過將塊裝置(例如,傳統硬碟)的一些資料動態遷移到更快、更小的裝置(例如,SSD)來提高其效能。
這種裝置對映器解決方案允許我們在 dm 堆疊的不同級別插入此快取,例如在精簡配置池的資料裝置之上。與虛擬記憶體系統更緊密整合的快取解決方案應該提供更好的效能。
該目標重用了精簡配置庫中使用的元資料庫。
關於何時遷移以及遷移哪些資料的決定留給了外掛策略模組。我們已經編寫了其中幾個用於實驗,我們希望其他人能為特定的 I/O 場景(例如虛擬機器映象伺服器)貢獻更多。
術語表¶
- 遷移
將邏輯塊的主副本從一個裝置移動到另一個裝置。
- 提升
從慢速裝置到快速裝置的遷移。
- 降級
從快速裝置到慢速裝置的遷移。
原始裝置總是包含邏輯塊的副本,該副本可能過時或與快取裝置上的副本保持同步(取決於策略)。
設計¶
子裝置¶
該目標透過向其傳遞三個裝置(以及稍後詳述的其他引數)來構建
原始裝置 - 大型、慢速的裝置。
快取裝置 - 小型、快速的裝置。
一個小的元資料裝置 - 記錄哪些塊在快取中、哪些是髒的,以及供策略物件使用的額外提示。這些資訊可以放在快取裝置上,但將其分離允許卷管理器以不同方式配置它,例如作為映象以增加魯棒性。此元資料裝置只能由一個快取裝置使用。
固定塊大小¶
原始裝置被劃分為固定大小的塊。此塊大小在您首次建立快取時可配置。通常我們使用的塊大小為 256KB - 1024KB。塊大小必須在 64 個扇區(32KB)到 2097152 個扇區(1GB)之間,並且是 64 個扇區(32KB)的倍數。
固定塊大小大大簡化了目標。但這也是一種折衷。例如,一個塊的一小部分可能被頻繁訪問,但整個塊都將被提升到快取中。因此,大塊大小不好,因為它們浪費快取空間。而小塊大小也不好,因為它們增加了元資料量(包括在記憶體中和磁碟上)。
快取操作模式¶
快取有三種操作模式:回寫(writeback)、直寫(writethrough)和直通(passthrough)。
如果選擇預設的回寫模式,則對已快取塊的寫入將僅寫入快取,並且該塊在元資料中將被標記為髒。
如果選擇直寫模式,則對已快取塊的寫入只有在同時寫入原始裝置和快取裝置後才會完成。乾淨的塊應保持乾淨。
如果選擇直通模式(在快取內容與原始裝置不同步時很有用),則所有讀取都從原始裝置提供(所有讀取都未命中快取),並且所有寫入都轉發到原始裝置;此外,寫入命中會導致快取塊失效。要啟用直通模式,快取必須是乾淨的。直通模式允許啟用快取裝置而無需擔心一致性。現有的一致性會得到維護,儘管隨著寫入的進行,快取會逐漸“冷卻”。如果以後可以透過驗證或使用“invalidate_cblocks”訊息來建立快取的一致性,則快取裝置可以在仍然“熱”的情況下轉換為直寫或回寫模式。否則,可以在轉換為所需操作模式之前丟棄快取內容。
提供了一個簡單的清理策略,它將清理(回寫)快取中所有髒塊。這在停用快取或縮小快取時很有用。縮小快取的快速裝置要求所有被移除區域中的快取塊都是乾淨的。如果從快取中移除的區域仍然包含髒塊,則調整大小將失敗。必須注意,在快取乾淨之前,絕不能減小用於快取快速裝置的卷。如果使用回寫模式,這一點尤為重要。直寫和直通模式已經保持快取乾淨。未來支援在指定閾值之上部分清理快取,將允許在調整大小時保持快取“熱”並處於回寫模式。
遷移限流¶
在原始裝置和快取裝置之間遷移資料會佔用頻寬。使用者可以設定一個限流器,以防止在任何時候發生超過一定量的資料遷移。目前我們沒有考慮流向裝置的正常 I/O 流量。這裡需要做更多工作,以避免在 I/O 峰值時進行遷移。
目前,可以使用訊息“migration_threshold <#sectors>”來設定正在遷移的最大扇區數量,預設值為 2048 個扇區(1MB)。
更新磁碟元資料¶
每當寫入 FLUSH 或 FUA bio 時,磁碟元資料就會被提交。如果沒有此類請求,則每秒都會發生提交。這意味著快取的行為類似於具有易失性寫入快取的物理磁碟。如果斷電,您可能會丟失一些最近的寫入。無論發生任何崩潰,元資料都應始終保持一致。
快取塊的“髒”狀態變化過於頻繁,我們無法即時更新它。因此我們將其視為一個提示。在正常操作中,當 dm 裝置掛起時,它將被寫入。如果系統崩潰,所有快取塊在重新啟動時都將被假定為髒塊。
每塊策略提示¶
策略外掛可以為每個快取塊儲存一段資料。這段資料的大小由策略決定,但應保持較小。與髒位標誌一樣,如果發生崩潰,這些資料會丟失,因此應該始終能夠有一個安全的後備值。
策略提示影響效能,而非正確性。
策略訊息¶
策略將有不同的可調引數,每個策略都有其特定引數,因此我們需要一種通用的方式來獲取和設定這些引數。裝置對映器訊息用於此目的。請參考策略編寫指南。
丟棄位集解析度¶
如果知道塊已被丟棄,我們可以在遷移過程中避免複製資料。一個典型的例子是 mkfs 丟棄整個塊裝置時。我們儲存一個位集來跟蹤塊的丟棄狀態。但是,我們允許這個位集具有與快取塊不同的塊大小。這是因為我們需要跟蹤所有原始裝置的丟棄狀態(與僅適用於較小快取裝置的髒位集相比)。
目標介面¶
建構函式¶
cache <metadata dev> <cache dev> <origin dev> <block size> <#feature args> [<feature arg>]* <policy> <#policy args> [policy args]*
元資料裝置
儲存持久元資料的快速裝置
快取裝置
儲存快取資料塊的快速裝置
原始裝置
儲存原始資料塊的慢速裝置
塊大小
以扇區為單位的快取單元大小
#功能引數
傳遞的功能引數數量
功能引數
直寫或直通(預設為回寫。)
策略
要使用的替換策略
#策略引數
傳遞給策略的鍵/值對對應的偶數個引數
策略引數
傳遞給策略的鍵/值對。例如 ‘sequential_threshold 1024’。詳情請參閱策略編寫指南。
可選功能引數有
直寫
直寫式快取,禁止快取塊內容與原始塊內容不同。如果沒有此引數,預設行為是出於效能原因稍後回寫快取塊內容,因此它們可能與相應的原始塊不同。
直通
一種降級模式,適用於各種快取一致性情況(例如,回滾底層儲存的快照)。讀寫操作始終訪問原始裝置。如果寫入一個已快取的原始塊,則該快取塊將被失效。要啟用直通模式,快取必須是乾淨的。
metadata2
使用元資料版本 2。這會將髒位儲存在一個單獨的 B 樹中,從而提高了關閉快取的速度。
no_discard_passdown
停用將丟棄操作從快取傳遞到原始資料裝置。
始終註冊一個名為“default”的策略。這是我們目前認為提供最佳綜合性能的策略的別名。
由於預設策略在不同核心之間可能有所不同,如果您依賴特定策略的特性,請始終按名稱請求它。
狀態¶
<metadata block size> <#used metadata blocks>/<#total metadata blocks>
<cache block size> <#used cache blocks>/<#total cache blocks>
<#read hits> <#read misses> <#write hits> <#write misses>
<#demotions> <#promotions> <#dirty> <#features> <features>*
<#core args> <core args>* <policy name> <#policy args> <policy args>*
<cache metadata mode>
元資料塊大小 |
每個元資料塊的固定大小(以扇區為單位) |
#已用元資料塊 |
已使用的元資料塊數量 |
#總元資料塊 |
元資料塊總數 |
快取塊大小 |
快取裝置的可配置塊大小(以扇區為單位) |
#已用快取塊 |
快取中駐留的塊數量 |
#總快取塊 |
快取塊總數 |
#讀取命中 |
READ bio 被對映到快取的次數 |
#讀取未命中 |
READ bio 被對映到原始裝置的次數 |
#寫入命中 |
WRITE bio 被對映到快取的次數 |
#寫入未命中 |
WRITE bio 被對映到原始裝置的次數 |
#降級次數 |
塊從快取中移除的次數 |
#提升次數 |
塊被移動到快取的次數 |
#髒塊 |
快取中與原始裝置不同的塊的數量 |
#功能引數 |
後續功能引數數量 |
功能引數 |
‘直寫’(可選) |
#核心引數 |
核心引數數量(必須是偶數) |
核心引數 |
用於調整核心的鍵/值對,例如 migration_threshold |
策略名稱 |
後續策略引數數量(必須是偶數) |
#策略引數 |
鍵/值對,例如 sequential_threshold |
策略引數 |
快取元資料模式 |
ro 表示只讀,rw 表示讀寫 |
在嚴重情況下,即使只讀模式被認為不安全,也將不再允許進一步的 I/O 操作,並且狀態將只包含字串“Fail”。此時應使用使用者空間恢復工具。 needs_check |
如果設定,則為‘needs_check’,否則為‘-’。元資料操作失敗,導致元資料超級塊中的 needs_check 標誌被設定。元資料裝置必須在快取完全恢復執行之前被停用並檢查/修復。“-”表示 needs_check 未設定。 |
訊息¶ |
策略將有不同的可調引數,每個策略都有其特定引數,因此我們需要一種通用的方式來獲取和設定這些引數。裝置對映器訊息用於此目的。(也可以使用 sysfs 介面。)
訊息格式為
例如
<key> <value>
失效是指從快取中移除一個條目而不將其回寫。快取塊可以透過 invalidate_cblocks 訊息失效,該訊息接受任意數量的 cblock 範圍。每個 cblock 範圍的結束值是“超出末尾一位”,這意味著 5-10 表示從 5 到 9 的值範圍。每個 cblock 必須表示為十進位制值,將來可能需要一種以十六進位制表示 cblock 範圍的變體訊息,以更好地支援大快取的高效失效。使用 invalidate_cblocks 時,快取必須處於直通模式。
dmsetup message my_cache 0 sequential_threshold 1024
示例¶
invalidate_cblocks [<cblock>|<cblock begin>-<cblock end>]*
失效是指從快取中移除一個條目而不將其回寫。快取塊可以透過 invalidate_cblocks 訊息失效,該訊息接受任意數量的 cblock 範圍。每個 cblock 範圍的結束值是“超出末尾一位”,這意味著 5-10 表示從 5 到 9 的值範圍。每個 cblock 必須表示為十進位制值,將來可能需要一種以十六進位制表示 cblock 範圍的變體訊息,以更好地支援大快取的高效失效。使用 invalidate_cblocks 時,快取必須處於直通模式。
dmsetup message my_cache 0 invalidate_cblocks 2345 3456-4567 5678-6789
測試套件可以在這裡找到
https://github.com/jthornber/device-mapper-test-suite
©核心開發社群。 | 由 Sphinx 5.3.0 & Alabaster 0.7.16 提供技術支援 | 頁面源
dmsetup create my_cache --table '0 41943040 cache /dev/mapper/metadata \
/dev/mapper/ssd /dev/mapper/origin 512 1 writeback default 0'
dmsetup create my_cache --table '0 41943040 cache /dev/mapper/metadata \
/dev/mapper/ssd /dev/mapper/origin 1024 1 writeback \
mq 4 sequential_threshold 1024 random_threshold 8'