ZFS:丢失驱动器后如何恢复正确数量的副本?

ZFS:丢失驱动器后如何恢复正确数量的副本?

使用 zfs 时,如果您copies=2丢失了包含部分副本的驱动器,您如何告诉系统应该为受影响的文件制作数据块的新副本?还是 zfs 在发现坏数据块后立即开始为额外副本添加数据块?

擦洗能起到这样的作用吗?

(v0.6.0.56-rc8,ZFS 池版本 28,ZFS 文件系统版本 5,Ubuntu 11.10)

答案1

“copies=2”(或 3)更适合用于没有冗余的池(单个磁盘或条带)。目标是能够恢复轻微的磁盘损坏,而不是整个设备故障。在后一种情况下,池无法挂载,因此无法进行重复块恢复。

如果有冗余(镜像/raidz/raidz2/raidz3),复制块与其他块没有什么不同,并且清理/重新镀银将重新创建它们。

答案2

我发现这个问题真的很有趣,在花了一个小时仔细阅读文档后,我深入研究了代码。以下是我发现的内容。

首先,介绍一些术语。复制块(即这些副本,与镜像相反)在写入时自动创建,但可能与原始副本位于同一虚拟设备 (vdev) 中,也可能不位于同一虚拟设备 (vdev) 中。另一方面,镜像块始终会反映到另一虚拟设备上。

但是,代码将这两种类型的块都称为子块。您将看到这里ditto 块只是子块io_vd == NULL(这是在写入函数中)。对于镜像块,io_vd将设置为相应的虚拟设备(例如,您的第二个磁盘)。

考虑到这一点,当谈到阅读部分,如果它不包含预期的good_copies,它会将所有子项(无论是镜像块还是复制块)视为潜在不安全,并且根据需要重写它们。因此,听起来你的问题的答案是 - 是的,当你至少有一个好的副本时它会重写它们,并且以下任一项:

  • 尝试读取数据时出现意外错误,
  • 您正在重新同步,或者
  • 你正在擦洗。

呼!也许有人会指出缺陷,但我很高兴通过这个小练习了解 ZFS,希望这会有所帮助!

答案3

@jlliagre 和其他人似乎认为,如果其中一个磁盘 (vdev) 坏了,但池不是冗余的 (mirror/raidz),那么整个 zpool 都会坏掉。事实并非如此;多磁盘游泳池总是即使不是镜像或 raidz,也能承受单个完整磁盘故障。

ZFS 元数据是总是至少复制 2 次,这样整个磁盘(或磁盘的任何部分)的彻底故障不会破坏文件系统。此外,许多文件(尤其是较小的文件)不会分散在所有磁盘上,因此不会一定磁盘故障会导致故障。原帖作者询问的是使用 ditto 块的多磁盘池(用户数据副本 > 1)。此处,单个完整磁盘故障绝不会导致任何数据丢失。ZFS总是会尝试将 ditto 块放置在远离原始块的地方,对于具有多个 vdev 的池,这总是意味着放在另一个 vdev 上(例外情况是一个 vdev 占池的 50% 以上,这种情况非常不常见)。文件系统元数据的复制次数也总是比 ditto 级别多 1 或 2 倍,因此它始终不会因磁盘故障而受到影响。此外,如果您的池有超过三个磁盘,那么您应该能够丢失其中的一半而不会丢失任何数据;ZFS 将 ditto 块存储在下一个磁盘上,因此只要您不丢失两个相邻的磁盘,就永远不会丢失数据。(ditto 的三个相邻磁盘故障=2)。

当有足够的数据副本来访问文件时(无论这些副本来自 ditto 块、镜像还是 raidz),则在访问文件时会修复所有丢失的数据副本。这就是清理的目的;读取所有数据并利用冗余副本修复任何损坏的数据。因此,直接回答 OP 的问题,您只需在更换故障驱动器后进行清理,所有副本都会恢复。

与往常一样,您可以通过创建池(其用于后备存储的 vdev 只是普通的稀疏文件)来轻松试验这些概念。通过删除或损坏 vdev 文件,您可以模拟任何类型的故障,并可以在此过程中验证池、文件系统和数据的完整性。

编辑:经过试验,看起来如果多磁盘非冗余池中某个磁盘发生故障且副本数>=2,zfs 将导致池故障。一个或多个磁盘上的部分数据损坏应该可以幸存,并且应该通过清理进行修复。

相关内容