![挂载文件系统时将 LVM 缓存设备添加到现有 LVM 卷组是否安全?](https://linux22.com/image/229780/%E6%8C%82%E8%BD%BD%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E6%97%B6%E5%B0%86%20LVM%20%E7%BC%93%E5%AD%98%E8%AE%BE%E5%A4%87%E6%B7%BB%E5%8A%A0%E5%88%B0%E7%8E%B0%E6%9C%89%20LVM%20%E5%8D%B7%E7%BB%84%E6%98%AF%E5%90%A6%E5%AE%89%E5%85%A8%EF%BC%9F.png)
我有一个现有的 LVM 卷组,其中有一个 10 TB 逻辑卷安装为 ext4 系统,并且正在使用中。
lvconvert --type cache --cachepool storage/lvmcache-data storage/data
当 ext4 文件系统已安装时运行该命令是否安全storage/data
?(storage/lvmcache-data
之前已经配置过,以防lvconvert --type cache-pool --cachemode writeback --poolmetadata storage/lvmcache-metadata storage/lvmcache-data
产生影响。)
我认为是的,将缓存动态添加到已安装文件系统的在线卷是安全的,但我无法找到任何文档。
答案1
LVM 的作者在任何地方都没有明确记录这一点,但根据https://blog.delouw.ch/2020/01/29/using-lvm-cache-for-storage-tiering/
另一个好处是dm缓存与 dm-writecache 相比,缓存可以是在线创建、激活和销毁。
这意味着只要您使用dm-cache
module 而不是dm-writecache
module,在逻辑卷已安装的情况下添加和删除 LVM 缓存应该是安全的。
请注意,LVMcachemode
设置writeback
与dm-writecache
.
此外,RedHat 文档位于https://access.redhat.com/documentation/en-us/red_hat_gluster_storage/3.5/html/administration_guide/sect-lvm_cache#idm140401735629408说如下:
19.8.3。配置 LVM 缓存
...
可以添加或删除缓存池在活跃量上,即使正在使用已安装的文件系统。然而,操作有一定的开销,绩效影响 将会看到,特别是在写回模式下删除缓存卷时,因为需要进行完整的数据同步。
我还通过以下测试验证了这一点:
在虚拟机上创建 4 个附加存储设备:
sda
(2 GB)、sdb
(4 GB)、sdc
(4 GB)、sdd
(1 GB)。这些设备的大小并不重要,我在这里使用不同大小的设备来说明 LVM 的灵活性。您可以假装较小的sdd
设备是最快的设备,并将用作缓存。使用 sda、sdb、sdc 构建一个 LVM 存储,获取所有设备的所有盘区(本例中调用卷组
storage
并调用逻辑卷):data
pvcreate /dev/sda /dev/sdb /dev/sdc vgcreate storage /dev/sda /dev/sdb /dev/sdc lvcreate -l100%FREE -n data storage mkfs.ext4 /dev/mapper/storage-data mkdir -p /root/test mount /dev/mapper/storage-data /root/test
在现实世界中,我建议创建比整个设备短一点的分区,并将这些分区用于 LVM 物理卷。这样可以更轻松地更换设备,因为来自不同制造商的“1 TB”设备可能会存在几兆字节的差异。我更喜欢保留最后约 100 MB 未分区的 SSD,以便能够在不同的 SSD 设备上创建相同大小的分区。作为奖励,SSD 设备可以使用磁盘上从未使用过的区域作为额外的磨损均衡区域。如果您使用廉价驱动器,我建议保留 10-20% 从未使用过,因为廉价驱动器通常在用户可访问区域之外的磨损均衡区域要少得多。保持某些用户可访问区域不受影响(或通过 释放
TRIM
)可以使固件拥有更多的磨损均衡区域,从而延长驱动器的使用寿命并通常提高其性能。在目录中的两个单独终端上并行启动两个 fio 测试循环
/root/test
:第一个循环:
while fio --name TEST --eta-newline=5s --filename=fio-tempfile.dat --rw=randwrite --size=500m --blocksize=4k --ioengine=libaio --fsync=1m --iodepth=1 --direct=1 --numjobs=1 --group_reporting --verify=sha1 --do_verify=0 --verify_state_save=1 --verify_backlog=1024 && fio --name TEST --eta-newline=5s --filename=fio-tempfile.dat --rw=randread --size=500m --blocksize=4k --ioengine=libaio --fsync=1m --iodepth=1 --direct=1 --numjobs=1 --group_reporting --verify=sha1 --do_verify=1 --verify_state_save=1 --verify_backlog=1024 --verify_dump=1 --verify_only ; do printf "\nOK -- %s\n\n\n" "$(date --iso=sec)"; done
第二个循环(在另一个终端中):
while fio --name TEST --eta-newline=5s --filename=fio-tempfile2.dat --rw=randwrite --size=500m --blocksize=4k --ioengine=libaio --fsync=1m --iodepth=4 --direct=1 --numjobs=4 --group_reporting --verify=sha1 --do_verify=0 --verify_state_save=1 --verify_backlog=1024 && fio --name TEST --eta-newline=5s --filename=fio-tempfile2.dat --rw=randread --size=500m --blocksize=4k --ioengine=libaio --fsync=1m --iodepth=2 --direct=1 --numjobs=8 --group_reporting --verify=sha1 --do_verify=1 --verify_state_save=1 --verify_backlog=1024 --verify_dump=1 --verify_only ; do printf "\nOK -- %s\n\n\n" "$(date --iso=sec)"; done
它们创建两个名为 和 的文件
fio-tempfile.dat
,并fio-tempfile2.dat
通过总共 5 个进程连续写入和验证,并验证文件的内容。我测试过dd
,如果修改单个字节,循环将检测到错误:dd if=/dev/zero of=fio-tempfile.dat seek=1000000 count=1 bs=1
一旦检测到错误,您可以重新启动循环,它将继续测试和验证存储,直到停止或发现错误。
将新的缓存设备 (
sdd
) 添加到此现有存储,同时不断运行上述测试循环以证明访问文件系统是安全的:pvcreate /dev/sdd vgextend storage /dev/sdd lvcreate -n lvmcache-data -l 98%FREE storage /dev/sdd lvcreate -n lvmcache-metadata -l 50%FREE storage /dev/sdd lvconvert --type cache-pool --cachemode writeback --poolmetadata storage/lvmcache-metadata storage/lvmcache-data lvconvert --type cache --cachepool storage/lvmcache-data storage/data
最后一个命令会动态添加 LVM 缓存设备,而不会导致数据损坏。缓存也将在系统重新启动后持续存在,不会出现任何问题。仅分配 98% 的数据缓存和 50% 的剩余空间 (1%) 的元数据缓存的原因是,用这些空间构建缓存池需要卷组中有一些可用空间,否则会失败。您也可以使用
cachevol
替代方法,cachepool
但第三方软件通常仅支持,cachepool
因为它是较旧的方法。两者具有相同的性能,cachepool
只是构建起来更复杂,但与第三方修复和诊断软件具有更好的互操作性,这就是我更喜欢使用它的原因。该cachepool
模式还支持使用单独的设备来存储元数据和数据,如果您有多个非常快的设备,这可以提高性能。如果您随后想要删除缓存设备,您可以即时执行以下操作,而不会损坏数据:
lvconvert --uncache storage/data
如果 LVM 缓存处于活动使用状态(例如上面的示例中正在运行测试循环),这将需要相当长的时间,并且它将继续显示状态,例如
Flushing 15610 blocks for cache storage/data. Flushing 11514 blocks for cache storage/data. Flushing 7418 blocks for cache storage/data. Flushing 5481 blocks for cache storage/data. ... Flushing 1 blocks for cache storage/data. Logical volume "lvmcache-data_cpool" successfully removed Logical volume storage/data is not cached.
看来刷新可能会停滞很长时间并继续显示相同数量的未刷新块,但你只需要继续等待。安装在 LVM 之上的文件系统始终保持工作状态。
uncache
我没有验证如果在操作过程中断电会发生什么。我假设 LVM 启动时缓存仍在使用中,您只需uncache
再次重新运行该操作即可。
请注意,在该uncache
命令之后,数据缓存和元数据缓存逻辑卷都将丢失(释放而没有任何历史记录),因此如果您想重新附加缓存设备,则必须从头开始构建它(所有lvcreate
和lvconvert
命令)步骤4)。操作完成后,缓存设备仍将是卷组的一部分uncache
,因此您无需重做。
和往常一样,在弄乱任何重要数据之前,请务必完成并验证最新的备份!
根据以下内容,上述 LVM 缓存设置将如下所示lsblk -sp
:
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
/dev/mapper/storage-data 253:3 0 10G 0 lvm /root/test
├─/dev/mapper/storage-lvmcache--data_cpool_cdata 253:0 0 996M 0 lvm
│ └─/dev/sdd 8:48 0 1G 0 disk
├─/dev/mapper/storage-lvmcache--data_cpool_cmeta 253:1 0 12M 0 lvm
│ └─/dev/sdd 8:48 0 1G 0 disk
└─/dev/mapper/storage-data_corig 253:2 0 10G 0 lvm
├─/dev/sda 8:0 0 2G 0 disk
├─/dev/sdb 8:16 0 4G 0 disk
└─/dev/sdc 8:32 0 4G 0 disk
有关 LVM 缓存使用的一些其他提示:
即使选择保留在缓存中的内容的逻辑是全自动的,您也可以稍微调整 LVM 缓存。看man lvmcache
了解完整详情。一些例子:
列出当前缓存设置(不会列出默认值):
lvs -o cachesettings storage/data
清除所有缓存设置(所有内容均使用默认值):
lvchange --cachesettings '' storage/data
当超过 10% 的缓存用于写缓冲时,调整缓存以始终开始将写缓存刷新到后备存储:
lvchange --cachesettings 'high_watermark=10' storage/data
调整缓存,以便在因任何原因启动刷新后有任何需要刷新的内容时继续刷新写缓存:
lvchange --cachesettings 'low_watermark=0' storage/data
调整缓存以在访问后备存储时自动暂停刷新 50 毫秒(避免引入刷新延迟)
lvchange --cachesettings 'pause_writeback=50' storage/data
当数据在缓存中超过 60 秒时,即使少量数据也会自动刷新到后备存储:
lvchange --cachesettings 'autocommit_time=60000' storage/data