28 持續性記憶體 #
本章包含關於使用裝備非揮發性主記憶體的 SUSE Linux Enterprise 的額外資訊。此類記憶體稱做持續性記憶體,由一或多個 NVDIMM 構成。
28.1 簡介 #
永續性記憶體是一種新型電腦儲存,其速度接近動態 RAM (DRAM),但同時具備 RAM 的逐位元組定址能力,以及固態硬碟 (SSD) 的效能。
SUSE 目前支援在採用 AMD64/Intel 64 和 POWER 架構的機器上,對 SUSE Linux Enterprise Server 使用持續性記憶體。
與傳統的 RAM 一樣,持續性記憶體直接安裝在主機板上的記憶體插槽中。因此,它的實體板型規格與 RAM 相同,以 DIMM 的形式提供。這些記憶體稱做 NVDIMM:非揮發性雙列直插式記憶體模組。
不過,與 RAM 不同,持續性記憶體在多個方面類似於快閃記憶體式 SSD。後兩者採用固態記憶體電路形式,但除此之外,兩者都提供非揮發性儲存:系統斷電或者重新啟動後,記憶體中的內容會得到保留。使用這兩種媒體時,寫入資料的速度比讀取資料要慢;兩者都支援有限的重新寫入週期數。最後,與 SSD 一樣,如果在特定的應用方案中,更適合對持續性記憶體進行磁區層級的存取,則也可以這樣做。
不同的型號使用不同形式的電子儲存媒體 (例如 Intel 3D XPoint),或者將 NAND 快閃記憶體與 DRAM 結合使用。另外,業界正在開發新式的非揮發性 RAM。這意味著,不同的廠商和 NVDIMM 型號會提供不同的效能與持久性特徵。
由於涉及的儲存技術處於早期開發階段,不同廠商的硬體可能存在不同的限制。因此,以下陳述適用於一般性場景。
持續性記憶體的速度最多比 DRAM 要慢 10 倍,但比快閃記憶體要快大約 1000 倍。可在其中逐位元組重新寫入資料,而不像在快閃記憶體中一樣,需要抹除整個磁區,然後重新寫入資料。最後,儘管重新寫入週期數有限,但大部分形式的持續性記憶體可以處理數百萬次重新寫入,相比之下,快閃記憶體只能處理數千個週期。
這會產生兩種重要結果:
使用最新技術無法執行僅包含持續性記憶體的系統,因此無法實現完全非揮發性的主記憶體。必須混合使用傳統的 RAM 和 NVDIMM。作業系統和應用程式將在傳統 RAM 中執行,而 NVDIMM 則可當成速度極快的輔助儲存。
由於不同廠商的持續性記憶體效能特徵不同,程式設計師可能需要考慮到特定伺服器中 NVDIMM 的硬體規格,包括 NVDIMM 的數目,以及它們可以裝入哪些記憶體插槽。顯然,這會對監管程式的使用、不同主機之間的軟體移轉等造成影響。
ACPI 標準版本 6 中定義了此新式儲存子系統。但是,libnvdimm
支援該標準頒佈之前的 NVDIMM,這些記憶體的使用方式相同。
28.2 詞彙 #
- 區域
區域是持續性記憶體中可劃分為一或多個名稱空間的區塊。如果不事先將某個區域配置到名稱空間,則您無法存取該區域的持續性記憶體。
- 名稱空間
非揮發性儲存的單個連續定址範圍,相當於 NVM Express SSD 的名稱空間,或 SCSI 邏輯單位 (LUN)。名稱空間做為獨立區塊裝置顯示在伺服器的
/dev
目錄中。根據所需的存取方法,名稱空間可將多個 NVDIMM 中的儲存合併成較大磁碟區,或者允許將這些儲存分割成較小的磁碟區。- 模式
每個名稱空間還具有一種模式,該模式定義要為該名稱空間啟用哪些 NVDIMM 功能。同一父區域的旁支名稱空間一律具有相同的類型,但可將其設定為使用不同的模式。名稱空間模式包括:
- devdax
裝置 DAX 模式。建立單字元裝置檔案 (
/dev/daxX.Y
).不需要建立檔案系統。- fsdax
檔案系統 DAX 模式。如果未指定其他模式,則使用預設值。建立區塊裝置 (
/dev/pmemX [.Y]
),支援將 DAX 用於ext4
或XFS
。- 磁區
適用於不執行中繼資料檢查總數計算的傳統檔案系統。適用於小型開機磁碟區。與其他作業系統相容。
- raw
不包含標籤或中繼資料的記憶體磁碟。不支援 DAX。與其他作業系統相容。
注意SUSE 不支援
raw
模式。無法在raw
名稱空間中掛接檔案系統。
- 類型
每個名稱空間和區域都有一種類型,該類型定義如何存取與該名稱空間或區域關聯的持續性記憶體。名稱空間的類型永遠與其父區域的類型相同。有兩種不同的類型:「永續性記憶體」(可使用兩種不同的方式進行設定),以及已廢棄的「區塊模式」。
- 持續性記憶體 (PMEM)
與 RAM 一樣,PMEM 儲存提供位元組層級的存取。使用 PMEM 時,單個名稱空間可以包含多個交錯式 NVDIMM,使這些 NVDIMM 均可用做單個裝置。
可使用兩種方式來設定 PMEM 名稱空間。
- 將 PMEM 與 DAX 搭配使用
為 Direct Access (DAX) 設定 PMEM 名稱空間後,存取記憶體時會繞過核心的頁面快取,直接進入媒體。軟體可以分別直接讀取或寫入該名稱空間的每個位元組。
- 使用區塊轉換表 (BTT) 的 PMEM
與在傳統磁碟機中一樣,將依磁區存取設定為以 BTT 模式執行的 PMEM 名稱空間,而不是像在 RAM 中一樣,採用位元組定址模式。某個轉譯表機制會將存取活動批次處理成磁區大小的單元。
BTT 的優點是具有資料保護功能。該儲存子系統可確保完全寫入基礎媒體的每個磁區。如果無法完全寫入某個磁區 (即,如果寫入操作由於某個原因失敗),整個磁區將會復原到其先前的狀態。因此,無法在給定的磁區中進行部分寫入。
此外,核心會快取對 BTT 名稱空間的存取。
缺點在於,BTT 名稱空間不支援 DAX。
- 區塊模式 (BLK)
區塊模式儲存將每個 NVDIMM 做為獨立的裝置進行定址。此模式已遭廢棄,且不再受支援。
除
devdax
名稱空間以外,其他所有類型也必須使用檔案系統格式化,如同使用傳統驅動器一樣。SUSE Linux Enterprise Server 支援將ext2
、ext4
和XFS
檔案系統用於此目的。- 直接存取 (DAX)
DAX 允許將永續性記憶體直接對應成程序的位址空間 (例如,使用
mmap
系統呼叫進行對應)。- DIMM 實體位址 (DPA)
在單個 DIMM 的記憶體中用做偏移量的記憶體位址;也就是說,在該 DIMM 中用做最低可定址位元組的從零開始的位址。
- 標籤
儲存在 NVDIMM 中的中繼資料,例如名稱空間定義。可以使用 DSM 存取這些資料。
- 裝置特定的方法 (DSM)
用於存取 NVDIMM 中韌體的 ACPI 方法。
28.3 使用案例 #
28.3.1 將 PMEM 與 DAX 搭配使用 #
必須注意,這種記憶體存取方式不是交易性的。如果發生斷電或其他系統故障,資料可能不會完全寫入儲存。僅當應用程式可以處理部分寫入資料的情況時,PMEM 儲存才適用。
28.3.1.1 可受益於較大位元組可定址儲存容量的應用程式 #
如果伺服器代管的某個應用程式可逐位元組直接使用較大的快速儲存容量,則程式設計師可以使用 mmap
系統呼叫,將持續性記憶體區塊直接放入該應用程式的位址空間,而無需使用任何額外的系統 RAM。
28.3.1.2 避免使用核心頁面快取 #
如果您想要節省用於頁面快取的 RAM,而不希望將 RAM 配置給應用程式,請避免使用核心頁面快取。例如,可以專門使用非揮發性記憶體來儲存虛擬機器 (VM) 影像。由於這些影像不會快取,因此可以減少主機上的快取使用量,從而可在每部主機上設定更多的 VM。
28.3.2 將 PMEM 與 BTT 搭配使用 #
當您想要使用一組 NVDIMM 中的持續性記憶體做為類似磁碟的極速儲存池時,此方法非常有用。例如,將檔案系統日誌置於使用 BTT 的 PMEM 上,可以提升在發生電源中斷或其他突發性中斷情況後所執行檔案系統復原的可靠性 (請參閱第 28.5.3 節 「建立使用 BTT 的 PMEM 名稱空間」)。
對於應用程式而言,此類裝置僅顯示為極速 SSD,並可像其他任何儲存裝置一樣供您使用。例如,LVM 可以排佈在永續性記憶體的頂層,如往常一樣正常運作。
BTT 的優點在於可以保證磁區寫入的不可部分完成性,因此,即使是依存於資料完整性的複雜應用程式也能保持正常運作。可透過標準的錯誤報告通道來執行媒體錯誤報告。
28.4 用於管理持續性記憶體的工具 #
若要管理持續性記憶體,必須安裝 ndctl
套件。安裝此套件也會安裝 libndctl
套件,後者提供一組使用者空間庫來設定 NVDIMM。
這些工具透過 libnvdimm
庫執行。該庫支援三種類型的 NVDIMM:
PMEM
BLK
同步 PMEM 和 BLK。
ndctl
公用程式提供一系列有用的 man
頁面。可使用以下指令存取這些頁面:
tux >
ndctl help subcommand
若要查看可用子指令的清單,請使用:
tux >
ndctl --list-cmds
可用的子指令包括:
- version
顯示 NVDIMM 支援工具的目前版本。
- enable-namespace
使指定的名稱空間可供使用。
- disable-namespace
防止使用指定的名稱空間。
- create-namespace
從指定的儲存裝置建立新名稱空間。
- destroy-namespace
移除指定的名稱空間。
- enable-region
使指定的區域可供使用。
- disable-region
防止使用指定的區域。
- zero-labels
抹除裝置中的中繼資料。
- read-labels
取回指定裝置的中繼資料。
- list
顯示可用的裝置。
- help
顯示關於工具用法的資訊。
28.5 設定持續性記憶體 #
28.5.1 檢視可用的 NVDIMM 儲存 #
可以使用 ndctl
list
指令列出系統中所有可用的 NVDIMM。
在以下範例中,系統包含三個 NVDIMM,這些 NVDIMM 位於單個三通道交錯集內。
root #
ndctl list --dimms
[ { "dev":"nmem2", "id":"8089-00-0000-12325476" }, { "dev":"nmem1", "id":"8089-00-0000-11325476" }, { "dev":"nmem0", "id":"8089-00-0000-10325476" } ]
結合不同的參數執行 ndctl
list
還可以列出可用的區域。
區域可能不按數字順序顯示。
請注意,儘管只有三個 NVDIMM,但它們卻顯示為四個區域。
root #
ndctl list --regions
[ { "dev":"region1", "size":68182605824, "available_size":68182605824, "type":"blk" }, { "dev":"region3", "size":202937204736, "available_size":202937204736, "type":"pmem", "iset_id":5903239628671731251 }, { "dev":"region0", "size":68182605824, "available_size":68182605824, "type":"blk" }, { "dev":"region2", "size":68182605824, "available_size":68182605824, "type":"blk" } ]
空間以兩種不同的形式顯示:三個 BLK 類型的獨立 64 GB 區域,或者一個 PMEM 類型的合併 189 GB 區域,後者將三個交錯式 NVDIMM 中的所有空間表示為單個磁碟區。
請注意,available_size
的顯示值與 size
的顯示值相同。這意味著尚未配置任何空間。
28.5.2 將儲存設定為使用 DAX 的單個 PMEM 名稱空間 #
第一個範例將三個 NVDIMM 設定為使用 Direct Access (DAX) 的單個 PMEM 名稱空間。
第一個步驟是建立新的名稱空間。
root #
ndctl create-namespace --type=pmem --mode=fsdax --map=memory
{ "dev":"namespace3.0", "mode":"memory", "size":199764213760, "uuid":"dc8ebb84-c564-4248-9e8d-e18543c39b69", "blockdev":"pmem3" }
如此會建立支援 DAX 的區塊裝置 /dev/pmem3
。裝置名稱中的 3
承襲自父區域號碼 (在本例中為 region3
)。
--map=memory
選項從 NVDIMM 中設定出一部分 PMEM 儲存空間,以便可以使用這些空間來配置內部核心資料結構 (稱做結構頁面
)。如此即可將新的 PMEM 名稱空間與 O_DIRECT I/O
和 RDMA
等功能搭配使用。
最終 PMEM 名稱空間的容量之所以小於父 PMEM 區域,是因為有一部分持續性記憶體保留給了核心資料結構。
接下來,我們驗證新的區塊裝置是否可用於作業系統:
root #
fdisk -l /dev/pmem3
Disk /dev/pmem3: 186 GiB, 199764213760 bytes, 390164480 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 4096 bytes I/O size (minimum/optimal): 4096 bytes / 4096 bytes
與其他任何磁碟機一樣,在使用該裝置之前,必須先將其格式化。在此範例中,我們使用 XFS 將其格式化:
root #
mkfs.xfs /dev/pmem3
meta-data=/dev/pmem3 isize=256 agcount=4, agsize=12192640 blks = sectsz=4096 attr=2, projid32bit=1 = crc=0 finobt=0, sparse=0 data = bsize=4096 blocks=48770560, imaxpct=25 = sunit=0 swidth=0 blks naming =version 2 bsize=4096 ascii-ci=0 ftype=1 log =internal log bsize=4096 blocks=23813, version=2 = sectsz=4096 sunit=1 blks, lazy-count=1 realtime =none extsz=4096 blocks=0, rtextents=0
接下來,可將新的磁碟機掛接到某個目錄:
root #
mount -o dax /dev/pmem3 /mnt/pmem3
然後,可以驗證是否得到了一個支援 DAX 的裝置:
root #
mount | grep dax
/dev/pmem3 on /mnt/pmem3 type xfs (rw,relatime,attr2,dax,inode64,noquota)
結果是,我們已得到一個使用 XFS 檔案系統格式化的,且掛接有 DAX 的 PMEM 名稱空間。
對該檔案系統中的檔案進行任何 mmap()
呼叫,都會傳回直接對應至 NVDIMM 上的持續性記憶體的虛擬位址,並且會完全繞過頁面快取。
對該檔案系統中的檔案進行任何 fsync
或 msync
呼叫仍可確定將修改後的資料完全寫入 NVDIMM。這些呼叫會衝洗透過 mmap
對應在使用者空間中修改的任何頁面的關聯處理器快取行。
28.5.2.1 移除名稱空間 #
在建立使用相同儲存的其他任何磁碟區類型之前,我們必須卸載此 PMEM 磁碟區,然後將其移除。
首先卸載該磁碟區:
root #
umount /mnt/pmem3
然後停用名稱空間。
root #
ndctl disable-namespace namespace3.0
disabled 1 namespace
然後刪除該磁碟區:
root #
ndctl destroy-namespace namespace3.0
destroyed 1 namespace
28.5.3 建立使用 BTT 的 PMEM 名稱空間 #
BTT 提供不可部分完成性磁區寫入,因此,當您需要資料保護 (例如,為 Ext4 和 XFS 日誌提供資料保護) 時,BTT 會是個不錯的選擇。如果發生電源失敗,日誌將受到保護且可復原。以下範例展示如何建立使用 BTT 的磁區模式 PMEM 名稱空間,以及如何將檔案系統日誌置於此名稱空間。
root #
ndctl create-namespace --type=pmem --mode=sector
{ "dev":"namespace3.0", "mode":"sector", "uuid":"51ab652d-7f20-44ea-b51d-5670454f8b9b", "sector_size":4096, "blockdev":"pmem3s" }
接下來,驗證新裝置是否存在:
root #
fdisk -l /dev/pmem3s
Disk /dev/pmem3s: 188.8 GiB, 202738135040 bytes, 49496615 sectors Units: sectors of 1 * 4096 = 4096 bytes Sector size (logical/physical): 4096 bytes / 4096 bytes I/O size (minimum/optimal): 4096 bytes / 4096 bytes
與前面設定的支援 DAX 的 PMEM 名稱空間一樣,這個支援 BTT 的 PMEM 名稱空間也會佔用 NVDIMM 中的所有可用儲存。
裝置名稱 (/dev/pmem3s
) 中的後置 s
表示磁區
(sector),可用於輕鬆辨別設定為使用 BTT 的名稱空間。
可依前一範例中所述格式化和掛接磁碟區。
這裡顯示的 PMEM 名稱空間不能使用 DAX。它會使用 BTT 來提供磁區寫入不可部分完成性。每次透過 PMEM 區塊驅動程式進行磁區寫入時,BTT 都會配置一個新的磁區來接收新資料。完全寫入新資料後,BTT 將以不可部分完成性的方式更新其內部對應結構,使新寫入的資料可供應用程式使用。如果在此過程中的任意時點發生電源故障,則寫入內容將會完全遺失,在這種情況下,應用程式可以存取其舊資料,而這些資料仍舊保持不變。如此可以防止出現所謂「磁區撕裂」的情況。
與其他任何標準區塊裝置一樣,可以使用某種檔案系統格式化這個支援 BTT 的 PMEM 名稱空間,並在該檔案系統中使用它。無法將該名稱空間與 DAX 搭配使用。但是,此區塊裝置中檔案的 mmap
對應會使用頁面快取。
28.5.4 將檔案系統日誌置於 PMEM/BTT 上 #
當您將檔案系統日誌置於一部獨立的裝置上時,該裝置使用的檔案系統區塊大小必須與該檔案系統相同。此大小很有可能是 4096,您可以使用以下指令尋找區塊大小:
root #
blockdev --getbsz /dev/sda3
下面的範例會在獨立的 NVDIMM 裝置上建立新的 Ext4 日誌,並在 SATA 裝置上建立檔案系統,然後將新檔案系統關聯到該日誌:
root #
mke2fs -b 4096 -O journal_dev /dev/pmem3s
root #
mkfs.ext4 -J device=/dev/pmem3s /dev/sda3
下面的範例會在 SATA 磁碟機上建立新的 XFS 檔案系統,並在一部獨立的 NVDIMM 裝置上建立日誌:
root #
mkfs.xfs -l logdev=/dev/pmem3s /dev/sda3
如需選項的詳細資訊,請參閱 man 8 mkfs.ext4
和 man 8 mkfs.ext4
。
28.6 更多資訊 #
以下清單中提供了更多關於此主題的資訊:
包含關於設定 NVDIMM 系統的指示、關於測試的資訊,以及關於啟用 NVDIMM 的規格連結。隨著 Linux 中 NVDIMM 支援功能的不斷發展,此網站的內容也會不斷擴充。
關於在 Linux 和其他作業系統中設定、使用非揮發性記憶體,以及對使用此類記憶體的系統進行程式設計的資訊。其中介紹了 NVM 庫 (NVML)。該庫旨在提供有用的 API,以便在使用者空間中進行持續性記憶體程式設計。
此文件面向核心開發人員,包含在目前 Linux 核心樹狀結構的「文件」資料夾中。其中探討了涉及啟用 NVDIMM 的不同核心模組,列出了關於核心實作的一些技術詳細資料,並介紹了
ndctl
工具使用的sysfs
核心介面。用於管理 Linux 核心中
libnvdimm
子系統的公用程式庫。此外還包含使用者空間庫,以及單元測試和文件。