dm-vdo¶
dm-vdo (虚拟数据优化器) 设备映射器目标提供块级重复数据删除、压缩和精简配置。作为设备映射器目标,它能够为存储栈添加这些功能,并与任何文件系统兼容。vdo 目标不提供数据损坏保护,而是依赖于其下方存储的完整性保护。强烈建议使用 lvm 来管理 vdo 卷。请参阅 lvmvdo(7)。
用户空间组件¶
格式化 vdo 卷需要使用“vdoformat”工具,该工具可在以下地址获取:
https://github.com/dm-vdo/vdo/
在大多数情况下,vdo 目标在下次启动时会自动从崩溃中恢复。如果遇到不可恢复的错误(在正常操作或崩溃恢复期间),目标将进入或以只读模式启动。由于只读模式表示数据丢失,因此必须采取积极行动才能使 vdo 退出只读模式。从同一仓库获取的“vdoforcerebuild”工具用于准备只读 vdo 退出只读模式。运行此工具后,vdo 目标将在下次启动时重建其元数据。尽管可能会丢失一些数据,但重建后的 vdo 元数据将内部一致,并且目标将再次可写。
该仓库还包含其他用户空间工具,可用于检查 vdo 目标的磁盘元数据。幸运的是,除了 dm-vdo 开发人员之外,这些工具很少用到。
元数据要求¶
每个 vdo 卷保留 3GB 空间用于元数据,具体取决于其配置,可能更多。检查重复数据删除和压缩节省的空间是否被元数据要求抵消掉,这很有帮助。特定数据集节省的空间估算可以使用 vdo 评估工具计算,该工具可在以下地址获取:
目标接口¶
表格行¶
<offset> <logical device size> vdo V4 <storage device>
<storage device size> <minimum I/O size> <block map cache size>
<block map era length> [optional arguments]
必需参数
- offset(偏移量)
vdo 卷逻辑空间起始的扇区偏移量。
- logical device size(逻辑设备大小)
vdo 卷将服务的设备大小,以扇区为单位。必须与 vdo 卷当前的逻辑大小匹配。
- storage device(存储设备)
保存 vdo 卷数据和元数据的设备。
- storage device size(存储设备大小)
保存 vdo 卷的设备大小,以 4096 字节块的数量表示。必须与 vdo 卷当前的大小匹配。
- minimum I/O size(最小 I/O 大小)
此 vdo 卷接受的最小 I/O 大小,以字节为单位。有效值为 512 或 4096。推荐值为 4096。
- block map cache size(块映射缓存大小)
块映射缓存的大小,以 4096 字节块的数量表示。最小和推荐值为 32768 块。如果逻辑线程计数非零,则缓存大小必须至少为每个逻辑线程 4096 块。
- block map era length(块映射时代长度)
块映射缓存写入已修改块映射页面的速度。较小的时代长度可能会减少重建所需的时间,但会增加正常操作期间的块映射写入。最大和推荐值为 16380;最小值为 1。
可选参数:¶
部分或所有这些参数可以指定为 <key> <value> 对。
线程相关参数
不同类别的工作被分配到独立的线程组,并且每个组中的线程数量可以单独配置。
如果 <hash>、<logical> 和 <physical> 都设置为 0,则所有三种线程类型处理的工作将由单个线程处理。如果这些值中的任何一个非零,则所有这些值都必须非零。
- ack(确认)
用于完成 bio 请求的线程数量。由于完成 bio 会在 vdo 卷外部调用任意完成函数,因此此类型的线程允许 vdo 卷即使在 bio 完成缓慢时也能继续处理请求。默认值为 1。
- bio(I/O 请求)
用于向底层存储发出 bio 请求的线程数量。此类型的线程允许 vdo 卷即使在 bio 提交缓慢时也能继续处理请求。默认值为 4。
- bioRotationInterval(bio 轮换间隔)
在切换到下一个线程之前,每个 bio 线程上排队的 bio 数量。该值必须大于 0 且不大于 1024;默认值为 64。
- cpu(CPU)
用于执行 CPU 密集型工作(例如散列和压缩)的线程数量。默认值为 1。
- hash(散列)
用于管理基于数据块散列值进行重复数据删除的数据比较的线程数量。默认值为 0。
- logical(逻辑)
用于管理基于传入 bio 逻辑地址进行缓存和锁定的线程数量。默认值为 0;最大值为 60。
- physical(物理)
用于管理底层存储设备管理的线程数量。在格式化时,会为 vdo 选择一个 slab 大小;vdo 存储设备必须足够大,以便每个物理线程至少有一个 slab。默认值为 0;最大值为 16。
其他参数
- maxDiscard(最大丢弃)
接受的丢弃 bio 的最大大小,以 4096 字节块为单位。对 vdo 卷的 I/O 请求通常被分割成 4096 字节块,并一次处理多达 2048 个。然而,对 vdo 卷的丢弃请求可以自动分割成更大的大小,在单个 bio 中最多可达 <maxDiscard> 个 4096 字节块,并且一次限制为 1500 个。增加此值可能会提供更好的整体性能,但会增加单个丢弃请求的延迟。默认值和最小值为 1;最大值为 UINT_MAX / 4096。
- deduplication(重复数据删除)
是否启用重复数据删除。默认值为“on”;可接受的值为“on”和“off”。
- compression(压缩)
是否启用压缩。默认值为“off”;可接受的值为“on”和“off”。
设备修改¶
修改后的表格可以加载到运行中、未暂停的 vdo 卷中。修改将在设备下次恢复时生效。可修改的参数有 <logical device size>、<physical device size>、<maxDiscard>、<compression> 和 <deduplication>。
如果逻辑设备大小或物理设备大小发生变化,成功恢复后 vdo 将存储新值并在未来的启动中要求它们。这两个参数不能减小。逻辑设备大小不能超过 4 PB。物理设备大小如果改变,必须至少增加 32832 个 4096 字节块,并且不能超过底层存储设备的大小。此外,在格式化 vdo 设备时,会选择一个 slab 大小:物理设备大小永远不能增加到提供 8192 个 slab 的大小以上,并且每次增加都必须足够大以添加至少一个新 slab。
示例
启动一个先前已格式化的 vdo 卷,具有 1 GB 逻辑空间和 1 GB 物理空间,存储到具有超过 1 GB 空间的 /dev/dm-1。
dmsetup create vdo0 --table \
"0 2097152 vdo V4 /dev/dm-1 262144 4096 32768 16380"
将逻辑大小增加到 4 GB。
dmsetup reload vdo0 --table \
"0 8388608 vdo V4 /dev/dm-1 262144 4096 32768 16380"
dmsetup resume vdo0
将物理大小增加到 2 GB。
dmsetup reload vdo0 --table \
"0 8388608 vdo V4 /dev/dm-1 524288 4096 32768 16380"
dmsetup resume vdo0
将物理大小再增加 1 GB 并增加最大丢弃扇区。
dmsetup reload vdo0 --table \
"0 10485760 vdo V4 /dev/dm-1 786432 4096 32768 16380 maxDiscard 8"
dmsetup resume vdo0
停止 vdo 卷。
dmsetup remove vdo0
再次启动 vdo 卷。请注意,逻辑和物理设备大小仍必须匹配,但其他参数可以更改。
dmsetup create vdo1 --table \
"0 10485760 vdo V4 /dev/dm-1 786432 512 65550 5000 hash 1 logical 3 physical 2"
消息¶
所有 vdo 设备都接受以下形式的消息:
dmsetup message <target-name> 0 <message-name> <message-parameters>
消息类型为:
- stats(统计信息)
输出 vdo 统计信息的当前视图。主要由 vdostats 用户空间程序用于解释输出缓冲区。
- config(配置)
输出有用的 vdo 配置信息。主要由希望重新创建类似 VDO 卷并想知道所使用的创建配置的用户使用。
- dump(转储)
将许多内部结构转储到系统日志。运行此操作并非总是安全的,因此应仅用于调试挂起的 vdo。指定要转储的结构的可选参数有:
viopool: 传入 bio 请求的 I/O 请求池 pools: 'viopool' 的同义词 vdo: 大多数管理磁盘数据的结构 queues: 有关每个 vdo 线程的基本信息 threads: 'queues' 的同义词 default: 等同于 'queues vdo' all: 以上所有。
- dump-on-shutdown(关机时转储)
下次 vdo 关闭时执行默认转储。
状态¶
<device> <operating mode> <in recovery> <index state>
<compression state> <physical blocks used> <total physical blocks>
device:
The name of the vdo volume.
operating mode:
The current operating mode of the vdo volume; values may be
'normal', 'recovering' (the volume has detected an issue
with its metadata and is attempting to repair itself), and
'read-only' (an error has occurred that forces the vdo
volume to only support read operations and not writes).
in recovery:
Whether the vdo volume is currently in recovery mode;
values may be 'recovering' or '-' which indicates not
recovering.
index state:
The current state of the deduplication index in the vdo
volume; values may be 'closed', 'closing', 'error',
'offline', 'online', 'opening', and 'unknown'.
compression state:
The current state of compression in the vdo volume; values
may be 'offline' and 'online'.
used physical blocks:
The number of physical blocks in use by the vdo volume.
total physical blocks:
The total number of physical blocks the vdo volume may use;
the difference between this value and the
<used physical blocks> is the number of blocks the vdo
volume has left before being full.
内存要求¶
vdo 目标需要固定 38 MB 的 RAM,以及以下随目标变化的量:
每 1 MB 配置的块映射缓存大小需要 1.15 MB RAM。块映射缓存至少需要 150 MB。
每 1 TB 逻辑空间需要 1.6 MB RAM。
卷管理的每 1 TB 物理存储需要 268 MB RAM。
重复数据删除索引需要额外的内存,其大小随重复数据删除窗口的大小而变化。对于密集索引,每 1 TB 窗口需要 1 GB RAM。对于稀疏索引,每 10 TB 窗口需要 1 GB RAM。索引配置在目标格式化时设置,不能修改。
模块参数¶
vdo 驱动程序有一个名为“log_level”的数值参数,它控制驱动程序日志的详细程度。默认设置为 6 (LOGLEVEL_INFO 和更严重的消息)。
运行时使用¶
使用 dm-vdo 时,了解其行为与其他存储目标的差异方式非常重要。
不能保证覆盖现有块会成功。由于底层存储可能被多次引用,覆盖现有块通常需要 vdo 有可用的空闲块。
当块不再使用时,发送这些块的丢弃请求可让 vdo 释放这些块的引用。如果 vdo 是精简配置的,丢弃未使用的块对于防止目标空间耗尽至关重要。然而,由于重复块的共享,任何给定逻辑块的丢弃请求都不能保证回收空间。
假设底层存储正确实现刷新请求,vdo 能够抵抗崩溃,但是,未刷新的写入在崩溃后可能持久化也可能不持久化。
对 vdo 目标的每次写入都涉及到大量的处理。然而,大部分工作是可并行化的。因此,vdo 目标在更高的 I/O 深度下能实现更好的吞吐量,并能支持高达 2048 个并行请求。
调优¶
vdo 设备有许多选项,如果没有完美了解工作负载,很难做出最佳选择。此外,大多数配置选项必须在 vdo 目标启动时设置,并且在不完全关闭它的情况下无法更改;目标处于活动状态时无法更改配置。理想情况下,在生产环境中部署 vdo 之前,应使用模拟工作负载进行调优。
最重要的调整值是块映射缓存大小。为了处理任何逻辑地址的请求,vdo 必须加载块映射中包含相关映射的部分。这些映射会被缓存。当工作集不适合缓存时,性能会下降。默认情况下,vdo 在 RAM 中分配 128 MB 的元数据缓存,以支持一次高效访问 100 GB 的逻辑空间。对于更大的工作集,应按比例放大。
逻辑和物理线程计数也应调整。逻辑线程控制块映射的不相交部分,因此额外的逻辑线程会增加并行性并可以提高吞吐量。物理线程控制数据块的不相交部分,因此额外的物理线程也可以提高吞吐量。然而,过多的线程会浪费资源并增加争用。
Bio 提交线程控制向底层存储发送 I/O 的并行性;线程越少意味着有更多机会重新排序 I/O 请求以获得性能优势,但同时也意味着每个 I/O 请求在提交之前需要等待更长时间。
Bio 确认线程用于完成 I/O 请求。这在专用线程上完成,因为执行 bio 回调所需的工作量无法由 vdo 本身控制。通常一个线程就足够了,但额外的线程可能也有益,尤其是在 bio 具有 CPU 密集型回调时。
CPU 线程用于散列和压缩;在启用压缩的工作负载中,更多的线程可能会导致更高的吞吐量。
散列线程用于按散列值对活动请求进行排序,并确定它们是否应进行重复数据删除;这些线程执行的最 CPU 密集型操作是 4096 字节数据块的比较。在大多数情况下,单个散列线程就足够了。