持久内存是一种新型计算机存储,结合了接近动态 RAM (DRAM) 的速度,以及 DRAM 的逐字节寻址能力,加上固态驱动器 (SSD) 的持久性。
SUSE 目前支持在 AMD64/Intel 64 和 POWER 架构的机器上使用 openSUSE Leap 的持久内存。
与传统的 RAM 类似,持久内存直接安装到主板内存插槽中。因此,它采用与 RAM 相同的物理封装形式——DIMM。这些被称为 NVDIMM:非易失性双列内存模块。
然而,与 RAM 不同,持久内存也与基于闪存的 SSD 相似。两者都基于固态存储电路的形式,但尽管如此,两者都提供非易失性存储:当系统关机或重新启动时,其内容会保留。对于这两种介质,写入数据比读取数据慢,并且两者都支持有限的重写周期。最后,也像 SSD 一样,如果这更适合特定应用程序,则可以对持久内存进行扇区级访问。
不同的型号使用不同的电子存储介质形式,例如 Intel 3D XPoint,或 NAND 闪存和 DRAM 的组合。新型非易失性 RAM 也在开发中。这意味着不同供应商和型号的 NVDIMM 提供不同的性能和耐用性特征。
由于所涉及的存储技术仍处于早期开发阶段,不同供应商的硬件可能会施加不同的限制。因此,以下陈述是概括性的。
持久内存比 DRAM 慢高达十倍,但比闪存存储快一千倍。它可以逐字节地重写,而不是闪存的整个扇区擦除和重写过程。最后,虽然重写周期有限,但大多数形式的持久内存可以处理数百万次的重写,而闪存存储只能处理数千次的循环。
这有两个重要的后果
目前的技术无法仅使用持久内存来运行系统,从而实现非易失性主内存。您必须混合使用传统的 RAM 和 NVDIMM。操作系统和应用程序将在传统的 RAM 中执行,而 NVDIMM 提供快速的辅助存储。
不同供应商持久内存的性能特征意味着程序员可能需要了解特定服务器中 NVDIMM 的硬件规格,包括 NVDIMM 的数量以及它们安装在哪个内存插槽中。这将影响虚拟机管理程序的使用、软件在不同主机之间的迁移等等。
这个新的存储子系统定义在 ACPI 标准的第 6 版中。但是,libnvdimm 支持非标准的 NVDIMM,并且可以使用相同的方式使用它们。
Intel Optane DIMM 内存可以在特定模式下使用
在 App Direct 模式下,Intel Optane 内存用作快速持久存储,作为 SSD 和 NVMe 设备的替代品。在此模式下,系统关机时数据会保留。
在 Memory 模式下,Intel Optane 内存作为 DRAM 的经济高效、大容量替代品。在此模式下,单独的 DRAM DIMM 作为最常访问数据的缓存,而 Optane DIMM 内存提供大容量内存。但是,与仅使用 DRAM 的系统相比,此模式在随机访问工作负载下速度较慢。如果您运行不利用此模式的 Optane 特定增强功能的应用程序,则内存性能可能会下降。在此模式下,系统关机时数据会丢失。
在 Mixed 模式下,Intel Optane 内存被分区,因此它可以同时在两种模式下工作。
一个 区域 是持久内存的一个块,可以划分为一个或多个 命名空间。在首先将其分配给命名空间之前,无法访问区域的持久内存。
一个单独的连续寻址的非易失性存储范围,可与 NVM Express SSD 命名空间或 SCSI 逻辑单元 (LUN) 进行比较。命名空间出现在服务器的 /dev 目录中,作为单独的块设备。根据所需的访问方法,命名空间可以合并来自多个 NVDIMM 的存储到更大的卷中,或者允许将其划分为更小的卷。
每个命名空间还具有一个 模式,该模式定义为该命名空间启用了哪些 NVDIMM 功能。同一父区域的同级命名空间始终具有相同的类型,但可以配置为具有不同的模式。命名空间模式包括
设备-DAX 模式。创建一个单字符设备文件 ( /dev/daxX.Y )。不需要创建文件系统。
文件系统-DAX 模式。如果没有指定其他模式,则为默认模式。创建一个块设备 (/dev/pmemX [.Y]),该设备支持 ext4 或 XFS 的 DAX。
对于不校验元数据的旧版文件系统。适用于小型启动卷。与其他操作系统兼容。
没有标签或元数据的内存磁盘。不支持 DAX。与其他操作系统兼容。
raw 模式不受 SUSE 支持。无法在 raw 命名空间上挂载文件系统。
每个命名空间和区域都有一个 类型,该类型定义了与该命名空间或区域关联的持久内存可以访问的方式。命名空间始终与其父区域具有相同的类型。有两种不同的类型:持久内存,可以以两种不同的方式配置,以及已弃用的块模式。
PMEM 存储提供类似 RAM 的字节级访问。使用 PMEM,单个命名空间可以包含多个交错的 NVDIMM,从而将它们全部用作单个设备。
有两种配置 PMEM 命名空间的方式。
为 Direct Access (DAX) 配置的 PMEM 命名空间意味着访问内存会绕过内核页面缓存并直接到达介质。软件可以直接读取或写入命名空间的每个字节。
配置为以 BTT 模式运行的 PMEM 命名空间以扇区为单位访问,就像传统的磁盘驱动器一样,而不是更像 RAM 的字节寻址模型。转换表机制将访问批量处理到扇区大小的单元中。
BTT 的优点是数据保护。存储子系统确保将每个扇区完全写入底层介质。如果无法完全写入扇区(即,如果写入操作由于某种原因而失败),则整个扇区将回滚到其先前状态。因此,不能部分写入给定的扇区。
此外,对 BTT 命名空间的访问由内核缓存。
缺点是 BTT 命名空间无法使用 DAX。
块模式存储将每个 NVDIMM 寻址为单独的设备。其使用已弃用,不再受支持。
除了 devdax 命名空间之外,所有其他类型都必须使用文件系统格式化,就像使用传统驱动器一样。openSUSE Leap 支持 ext2、ext4 和 XFS 文件系统。
DAX 允许将持久内存直接映射到进程的地址空间,例如使用 mmap 系统调用。
内存地址,作为单个 DIMM 内存中的偏移量;即,从该 DIMM 上可寻址的最低字节开始为零。
存储在 NVDIMM 上的元数据,例如命名空间定义。可以使用 DSM 访问这些元数据。
ACPI 方法,用于访问 NVDIMM 上的固件。
这种内存访问形式 不是事务性的。如果发生电源中断或其他系统故障,数据可能无法写入存储。PMEM 存储仅适用于应用程序可以处理部分写入数据的情况。
如果服务器将托管可以直接使用大量快速存储的应用程序,则程序员可以使用 mmap 系统调用将持久内存块直接放置在应用程序的地址空间中,而无需使用额外的系统 RAM。
当您希望将 NVDIMM 集合上的持久内存用作类似磁盘的快速存储池时,这将很有用。例如,将文件系统日志放在具有 BTT 的 PMEM 上可以提高电源故障或其他突然中断后文件系统恢复的可靠性(请参阅第 19.5.3 节,“使用 BTT 创建 PMEM 命名空间”)。
对于应用程序,这些设备看起来像快速的 SSD,并且可以像任何其他存储设备一样使用。例如,可以在持久内存之上分层 LVM,并且可以正常工作。
BTT 的优点是保证了扇区写入原子性,因此即使依赖数据完整性的复杂应用程序也会继续工作。媒体错误报告通过标准错误报告通道进行。
要管理持久内存,需要安装 ndctl 包。这还会安装 libndctl 包,该包提供一组用户空间库来配置 NVDIMM。
这些工具通过 libnvdimm 库工作,该库支持三种类型的 NVDIMM
PMEM
BLK
同时 PMEM 和 BLK
该 ndctl 实用程序具有一组有用的 man 页面,可以使用以下命令访问:
>ndctl help subcommand
要查看可用的子命令列表,请使用
>ndctl --list-cmds
可用的子命令包括
显示 NVDIMM 支持工具的当前版本。
使指定的命名空间可供使用。
防止使用指定的命名空间。
从指定的存储设备创建新的命名空间。
删除指定的命名空间。
使指定的区域可供使用。
阻止使用指定的区域。
擦除设备上的元数据。
检索指定设备的元数据。
显示可用设备。
显示有关使用该工具的信息。
可以使用 ndctl list 命令列出系统中的所有可用 NVDIMM。
在以下示例中,系统有三个 NVDIMM,它们在一个单一的、三通道交错集合中。
#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,但它们显示为四个区域。
#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" } ]
空间以两种不同的形式可用:要么是三个独立的 64 个 BLK 类型的区域,要么是一个组合的 189 GB PMEM 类型的区域,它将三个交错 NVDIMM 上的所有空间作为一个单一的卷呈现。
请注意,显示的 available_size 值与 size 值相同。这意味着尚未分配任何空间。
对于第一个示例,我们将三个 NVDIMM 配置为一个具有直接访问 (DAX) 的单个 PMEM 命名空间。
第一步是创建一个新的命名空间。
#ndctl create-namespace --type=pmem --mode=fsdax --map=memory{ "dev":"namespace3.0", "mode":"memory", "size":199764213760, "uuid":"dc8ebb84-c564-4248-9e8d-e18543c39b69", "blockdev":"pmem3" }
这将创建一个块设备 /dev/pmem3,它支持 DAX。设备名称中的 3 继承自父区域编号,在本例中为 region3。
--map=memory 选项预留了 NVDIMM 上 PMEM 存储空间的一部分,以便可以用来分配内部内核数据结构,称为 struct pages。这允许新的 PMEM 命名空间与 O_DIRECT I/O 和 RDMA 等功能一起使用。
为内核数据结构预留一些持久内存是导致生成的 PMEM 命名空间容量小于父 PMEM 区域的原因。
接下来,我们验证新的块设备是否对操作系统可用
#fdisk -l /dev/pmem3Disk /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 对其进行格式化
#mkfs.xfs /dev/pmem3meta-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
接下来,我们可以将新的驱动器挂载到目录
#mount -o dax /dev/pmem3 /mnt/pmem3
然后我们可以验证我们现在有一个 DAX 兼容的设备
#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 映射修改的任何页面关联的处理器缓存行。
BTT 提供扇区写入原子性,这使其成为需要数据保护的良好选择,例如 Ext4 和 XFS 日志。如果发生电源故障,日志将受到保护并应可恢复。以下示例演示如何以扇区模式创建具有 BTT 的 PMEM 命名空间,以及如何将文件系统日志放置在此命名空间中。
#ndctl create-namespace --type=pmem --mode=sector{ "dev":"namespace3.0", "mode":"sector", "uuid":"51ab652d-7f20-44ea-b51d-5670454f8b9b", "sector_size":4096, "blockdev":"pmem3s" }
接下来,验证新的设备是否存在
#fdisk -l /dev/pmem3sDisk /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 上的所有可用存储空间。
设备名称中的尾随 s (/dev/pmem3s) 代表 sector,可用于轻松区分配置为使用 BTT 的命名空间。
可以像前面的示例一样格式化和挂载该卷。
此处显示的 PMEM 命名空间无法使用 DAX。相反,它使用 BTT 来提供 扇区写入原子性。在通过 PMEM 块驱动器写入每个扇区时,BTT 将分配一个新的扇区来接收新的数据。BTT 在完全写入新数据后以原子方式更新其内部映射结构,以便应用程序可以使用新写入的数据。如果在此过程中任何时候发生电源故障,则写入将丢失,并且应用程序将可以访问其旧数据,仍然完好无损。这可以防止被称为 “撕裂扇区” 的情况。
此启用了 BTT 的 PMEM 命名空间可以像任何其他标准块设备一样格式化和使用。它不能与 DAX 一起使用。但是,此块设备上文件的 mmap 映射将使用页面缓存。
当您将文件系统日志放置在单独的设备上时,它必须使用与文件系统相同的块大小。最有可能的是 4096,您可以使用以下命令找到块大小
#blockdev --getbsz /dev/sda3
以下示例在单独的 NVDIMM 设备上创建一个新的 Ext4 日志,在 SATA 设备上创建文件系统,然后将新的文件系统附加到日志
#mke2fs -b 4096 -O journal_dev /dev/pmem3s#mkfs.ext4 -J device=/dev/pmem3s /dev/sda3
以下示例在 SATA 驱动器上创建一个新的 XFS 文件系统,并在单独的 NVDIMM 设备上创建日志
#mkfs.xfs -l logdev=/dev/pmem3s /dev/sda3
有关详细信息,请参阅 man 8 mkfs.ext4 和 man 8 mkfs.ext4。
有关此主题的更多信息可以在以下列表中找到
包含有关配置 NVDIMM 系统的说明、有关测试的信息以及与 NVDIMM 启用相关的规范链接。随着 Linux 中 NVDIMM 支持的发展,该站点也在发展。
有关在 Linux 和其他操作系统下配置、使用和编程具有非易失性内存的系统的信息。涵盖 NVM 库 (NVML),旨在为用户空间中的持久内存编程提供有用的 API。
面向内核开发人员,这是当前 Linux 内核树中的 Documentation 目录的一部分。它讨论了参与 NVDIMM 启用的不同内核模块,阐述了内核实现的详细信息,并讨论了 sysfs 接口到内核,该接口由 ndctl 工具使用。
用于管理 Linux 内核中 libnvdimm 子系统的实用程序库。还包含用户空间库以及单元测试和文档。