如何使用 RAM 磁盘上的缓存恢复缓存的 LVM?

如何使用 RAM 磁盘上的缓存恢复缓存的 LVM?

文章中有一个很好的方法,介绍如何使用 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

相关内容