在这文章中有一个很好的方法,介绍如何使用 RAM 磁盘作为传统 LVM 卷的缓存设备。
假设您有一个旧磁盘、大量 RAM 但没有 SSD,您可以使用此技术将磁盘性能提升到原始 RAM 吞吐量。
因此我在用于运行 Windows 10 的虚拟 VM 的 LVM 上执行了此操作。瞧:VM 内的磁盘吞吐量快了 4 倍(平均吞吐量,最适合在修补 Windows 时使用)。
一切都很好 - 直到我关闭我的 Linux 系统(CentOS 7)。
数据丢失!
关机不会分解该缓存。断电情况下也是如此(是的 - 会有数据丢失)。
但是 - 必须有一种方法可以恢复剩余的内容。但是 LVM 不允许您在缺少磁盘的 VG 上进行操作。
那么 - 有没有针对此案的处方?
喜欢
- 使用新磁盘恢复丢失的 LVM 缓存磁盘
- 强制清洁状态
- 再次访问缓存的 LV
在最后一步中,将修复文件系统并从备份中恢复丢失/损坏的文件(使用 rsync)。
答案1
您可以使用此技术将磁盘性能提升至本机 RAM 吞吐量
不,不完全是。一旦缓存中充满了写入,写入吞吐量就会降低到底层磁盘可以执行的水平。而且从备份磁盘进行的首次读取仍然很慢。缓存的 I/O 确实更快了。
这种方法非常危险,因为它不是永久性磁盘。当你能得到一个快速固态磁盘或硬件写入缓存时,我对这个实用性持怀疑态度,但测试故障模式很有趣。
这将导致数据丢失。仅当您备份了数据后才可以继续。
第一、无缓存。
# Create volume
pvcreate /dev/sdb
vgcreate vg /dev/sdb
lvcreate --size 400g --name lv vg
mkfs.xfs /dev/vg/lv
mkdir /mnt/lv
mount /dev/vg/lv /mnt/lv
# Write test
dd bs=1M if=/dev/zero of=/mnt/lv/zero count=10000
添加缓存。
# Create a RAM disk
modprobe brd rd_nr=1 rd_size=4585760 max_part=0
pvcreate /dev/ram0
vgextend vg /dev/ram0
# Create a cache
lvcreate -L 300M -n cache_meta vg /dev/ram0
lvcreate -L 4G -n cache_vol vg /dev/ram0
lvconvert –type cache-pool –poolmetadata vg/cache_meta –cachemode=writeback vg/cache_vol -y
# Add cache to a LV
lvconvert –type cache –cachepool vg/cache_vol vg/lv
# Write test
dd bs=1M if=/dev/zero of=/mnt/lv/zero2 count=10000
# Crash test
echo 'c' > /proc/sysrq-trigger
当它回来时,LVM 非常不高兴,卷无法访问。
[root@sf ~]# lvs
WARNING: Device for PV YpvOB5-PZLO-POFL-3Cf4-G1IB-gep8-6eU10R not found or rejected by a filter.
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
lv vg Cwi---C-p- 400.00g [cache_vol] [lv_corig]
[root@sf ~]# mount /dev/vg/lv /mnt/lv/
mount: special device /dev/vg/lv does not exist
[root@sf ~]# pvs
WARNING: Device for PV YpvOB5-PZLO-POFL-3Cf4-G1IB-gep8-6eU10R not found or rejected by a filter.
PV VG Fmt Attr PSize PFree
/dev/sdb vg lvm2 a-- <500.00g 99.70g
[unknown] vg lvm2 a-m 4.37g 80.00m
您甚至无法强制取消缓存,因为元数据有 I/O 错误。
[root@sf ~]# lvconvert --uncache vg/lv --force -y
WARNING: Device for PV YpvOB5-PZLO-POFL-3Cf4-G1IB-gep8-6eU10R not found or rejected by a filter.
WARNING: Cache pool data logical volume vg/cache_vol_cdata is missing.
WARNING: Cache pool metadata logical volume vg/cache_vol_cmeta is missing.
WARNING: Uncaching of partially missing writethrough cache volume vg/lv might destroy your data.
/dev/mapper/vg-cache_vol_cmeta: read failed: Input/output error
Failed to active cache locally vg/lv.
但是,您可以通过创建具有相同 UUID 的新 PV 来强制数据丢失。取消缓存以删除 LVM 认为其中仍有数据但已丢失的 ramdisk PV。您可以使用 重新添加新缓存lvconvert
,但根据此实验的结果,我不会这样做。
pvcreate --norestore --uuid YpvOB5-PZLO-POFL-3Cf4-G1IB-gep8-6eU10R /dev/ram0
lvconvert --uncache vg/lv
最后,检查文件系统是否有损坏。需要从备份中恢复才能使数据恢复到良好状态。
xfs_repair /dev/vg/lv
编辑:添加具有相同 UUID 的空 PV 似乎非常不安全。毕竟,lvconvert 拒绝取消缓存。如果您将元数据 LV 放在永久磁盘上,那么清理起来会容易一些。
# Same procedure but meta is on persistent storage.
lvcreate -L 300M -n cache_meta vg /dev/sdb
可以强制取消缓存。不要让“刷新 0 个块”输出让您放心,正在进行的写入已经丢失。然后可以删除丢失的 ramdisk,使 VG 再次保持一致。
[root@sf ~]# lvconvert --uncache vg/lv --force -y
WARNING: Device for PV YpvOB5-PZLO-POFL-3Cf4-G1IB-gep8-6eU10R not found or rejected by a filter.
WARNING: Cache pool data logical volume vg/cache_vol_cdata is missing.
WARNING: Uncaching of partially missing writethrough cache volume vg/lv might destroy your data.
Flushing 0 blocks for cache vg/lv.
Logical volume "cache_vol" successfully removed
Logical volume vg/lv is not cached.
[root@sf ~]# vgreduce --removemissing vg
WARNING: Device for PV YpvOB5-PZLO-POFL-3Cf4-G1IB-gep8-6eU10R not found or rejected by a filter.
Wrote out consistent volume group vg.
[root@sf ~]# pvs
PV VG Fmt Attr PSize PFree
/dev/sdb vg lvm2 a-- <500.00g <100.00g
答案2
我尝试遵循其他答案。但是,我没有将内存设置为缓存磁盘,而是另一个 SSD,并且 SSD 坏了。因此,答案对我来说不起作用,因为我无法创建另一个物理卷,因为我没有两次相同的 SSD。
因此我想出了另一个适用于更广泛场景的解决方案:
- 一切都和另一个答案一样
- 但在创建新的虚拟 pv 时,还需要进行一些调整,因为我们原来的 pv 已经完全消失了
# check again for available lvs and pvs
lvs -a
pvs -a
# create config backup of the vg with the missing cache pv
vgcfgbackup -f vgdata_backup.vg vg-data
# create a second backup
cp vgdata_backup.vg vgdata_new.vg
# open the config
nano vgdata_new.vg
# search for the size of your missing pv, the 512 is the block size, which can remain like this
truncate -s $((216825856 * 512)) test.img
# create a loopback device (virtual disk) from the created file
losetup /dev/loop101 ./test.img
# now create a pv from the new disk and insert your uuid which you can also find in the config backup
pvcreate --norestore --uuid VJW345-hle6-0yqY-Pgnm-ldWL-invq-OW4Vvc /dev/loop101
# now edit the config
# you have to adjust the path to your file, and probably the flags, like this
pv2 {
id = "VJW345-hle6-0yqY-Pgnm-ldWL-invq-OW4Vvc"
device = "/dev/loop101" # Hint only
status = ["ALLOCATABLE"]
flags = []
dev_size = 216825856 # 103,391 Gigabytes
pe_start = 2048
pe_count = 26467 # 103,387 Gigabytes
}
# now restore the new config
vgcfgrestore -f vgdata_new.vg vg-data
# check again
lvs -a
pvs -a
# FINALLY: you made it and you can uncache the vg
lvconvert --uncache vg-data/lv-0 --force