静态数据/磁盘一致性

静态数据/磁盘一致性

正如问题所说。

假设我想为我的 FreeNAS 池设置一个相当于脚本化“紧急按钮”的东西 - 我可以单击该按钮从 GUI 运行或在控制台/SSH 中执行,这会很快关闭可能正在读取或写入的所有内容,卸载文件系统,并且 - 理想情况下 - 静默其正在使用的磁盘或分区。

我不关心通过这样做而引起的其他软件或远程连接的错误,或者过早中止任何长文件传输,我只是希望它以最快的方式使池脱机,这与保持其一致性并可能给它一些任何挂起的写入完成并且池处于数据一致状态的秒数。

ZFS 命令建议的选项看起来并不乐观:zpool offline仅适用于单个设备,因此如果在一次删除一个磁盘的情况下进行写入,则可能会出现竞争状况;zpool export如果使用,则需要 -f 选项,并带有-f可能丢失数据的警告。人们可以file descriptors使用池或其设备(数千个或数十万个?)检查所有打开的情况,并手动强制关闭每个设备,但这可能会遇到竞争条件,因为它不会阻止同时创建新的文件描述符。我也不应该假设所有 ZFS 活动都是由要发送退出信号的远程文件服务守护进程列表来调节的,因为某些文件活动可能是本地的(cron/CLI/分离会话)。

因此,看看如何最好地安全、快速地使整个池脱机,它看起来umount可能是我最好的选择 - 它在文件系统级别工作,并且可以快速地脱机整个文件系统并作为一个整体单元,之后zpool export看起来它会然后能够以安全的方式实际完成并停止任何内部活动,而无需选择-f,使数据本身保持在保证一致的状态。如果正在进行原始磁盘活动(重新同步或清理),那么我想当池稍后恢复在线时,这将恢复或重新启动。

但 Even 似乎umount并没有完全做到这一点,因为zvol也可能有 iSCSI 目标正在使用。由于服务器不知道其结构,这些数据本质上无法保持一致,因此远程发起者在重新连接时必须尽最大努力进行数据修复。我对此表示同意,但我不确定是否需要某种命令来强制终止或使目标脱机,或者是否需要最佳实践。 (注:强制终止连接与关闭单个 fd 具有相同的问题。)

我知道,如果在写入时池突然退出 RW 状态,必然会出现某种数据丢失或问题。但只要它不失去一致性(在 ZFS 池和文件系统级别),那就没问题 - 任何正在更新的正在使用的文件/iSCSI 目标都必须在文件/块处于 ZFS 一致的情况下抓住机会但由于写入数据中途离线而导致数据无效状态。这是不可避免的,也不是这个问题的问题。

那么,我实际上需要执行哪些步骤,在保证池安全性和一致性的情况下尽快脱机正在使用的池 - 并且手动umount设置正在使用的 ZFS 文件系统(作为解决方案的一部分)是安全的或是否存在数据损坏的风险?

更新:在这里提及以防其他人发现这有用。接受的答案指出export -fzvols(iSCSI 等)可能存在问题。基于这个提示,我发现 FreeNAS 使用的 iSCSI 处理程序可以强制注销/终止会话,并且还有其他可以提前发出的有用的子命令 - 请参阅man ctladm。无论您的 zvols 用于什么目的,都可能有一些命令来结束它们的会话。)

答案1

免责声明:我目前手头没有太多链接和参考来备份以下所有内容,并且我没有对其进行广泛测试。这只是我在过去五到七年里读到的有关 ZFS 及其工作原理的总结,以及一些有限的自己的测试(不协调,但大多是随机重新启动)。

另外,下面所说的一切都没有考虑灾难性事件(服务器完全烧毁)、软件错误(ZFS 和主操作系统以及硬件控制器中的错误)和主动恶意(流氓管理、管理错误)。对于所有这些情况,您仍然需要定期且可恢复的备份!


静态数据/磁盘一致性

我不关心通过这样做而引起的其他软件或远程连接的错误,或者过早中止任何长文件传输,我只是希望它以最快的方式使池脱机,这与保持其一致性并可能给它一些任何挂起的写入完成并且池处于数据一致状态的秒数。

首先,好消息是:由于 ZFS 使用 CoW 和原子事务,即使突然断电,您现有的数据也将是安全的。这包括池布局和元数据。由于在新数据完全写入之前旧数据永远不会移动(事实上,它根本不会移动,只是重新分配),因此如果写入突然中断,该数据不会有任何危险。

此外,校验和(Merkle 哈希树)有助于证明重新启动期间没有发生任何不良情况,您可以通过清理池来检查这一点。如果您有冗余 vdev,ZFS 将自动更正它从已知良好副本中发现的任何错误。如果某些块以任何方式被损坏(例如,被一个不写入但声称写入的恶意磁盘控制器损坏),它们的校验和将与其他 vdev 的校验和不匹配,并且会显示错误。

飞行/写入模式中的数据以及最后 n 秒的数据丢失

同步和异步写入

通常,ZFS 会收集多个事务来加速对旋转驱动器的昂贵写入 - 定位 HDD 的写入磁头比实际写入需要更多时间,因此您需要尽可能排队,然后按顺序写出(更快) !)顺序(记住,我们有 CoW,这在这里很自然)。

这样做的缺点是,收集的时间越长,应用程序等待“写入成功”消息的时间就越长 - 这意味着您的系统将锁定几秒钟,这是不可接受的。更糟糕的是,如果断电,您将丢失所有要写入磁盘但尚未写入的数据。如果您的应用程序无法应对此问题,则可能会发生应用程序层损坏。

为了解决这个问题,添加了 ZIL(ZFS 意图日志)。所有同步事务都收集在此日志中(默认情况下存储在慢速池磁盘上,但可以存储在更快的镜像 SSD 上,称为 SLOG 设备),并且在存储后,将“写入成功”返回到可以继续执行其任务的应用程序(不再有长锁)。此外,所有异步事务都是在没有 ZIL 的情况下完成的,因此它们可以更快 - 只要应用程序为其数据调用正确的写入操作(同步与异步)。

ZFS 属性

现在是更有趣的部分 - 你的写入会发生什么?在那里,我们必须辨别文件系统的操作模式(它是 ZFS 属性,可以为每个文件系统单独设置)。三种可能的模式是(来自联机帮助页):

sync=standard
  This is the default option. Synchronous file system transactions
  (fsync, O_DSYNC, O_SYNC, etc) are written out (to the intent log)
  and then secondly all devices written are flushed to ensure
  the data is stable (not cached by device controllers).

sync=always
  For the ultra-cautious, every file system transaction is
  written and flushed to stable storage by a system call return.
  This obviously has a big performance penalty.

sync=disabled
  Synchronous requests are disabled.  File system transactions
  only commit to stable storage on the next DMU transaction group
  commit which can be many seconds.  This option gives the
  highest performance.  However, it is very dangerous as ZFS
  is ignoring the synchronous transaction demands of
  applications such as databases or NFS.
  Setting sync=disabled on the currently active root or /var
  file system may result in out-of-spec behavior, application data
  loss and increased vulnerability to replay attacks.
  This option does *NOT* affect ZFS on-disk consistency.
  Administrators should only use this when these risks are understood.

您会注意到,即使disabled选择了,您的池布局/内部一致性也不会受到影响 - 您只会丢失最后 5 秒的数据并且可能会将您的文件置于不正确的状态(例如,因为您的顶部有一个虚拟机需要同步写入,但您只提供了异步 zvol 作为后备数据存储)。

另一方面,如果你不想失去任何事,将所有文件系统设置为always并切换到高性能 SSD,至少对于 SLOG 设备而言如此(否则会遭受等待时间)。

standard是一种折衷方案,也是最灵活的——应用程序本身决定它需要哪种写入模式。如果您的应用程序很糟糕,您可能会遇到数据丢失的情况。如果他们表现良好,您将在给定的安全基线下获得最佳的性能。

池导出/导入:

来自文档关于zpool export

该命令在继续之前尝试卸载池中所有已安装的文件系统。如果任何文件系统无法卸载,您可以使用 -f 选项强制卸载它们。

如果导出时设备不可用,则无法将设备识别为干净导出。如果这些设备之一后来连接到没有任何工作设备的系统,它将显示为“潜在活动”。

如果池中正在使用 ZFS 卷,则即使使用 -f 选项也无法导出池。要导出包含 ZFS 卷的池,首先确保该卷的所有使用者不再处于活动状态。

这大致意味着三件事:

  • -f通过强制卸载所有文件系统来强制导出池,即使它们处于活动状态(不考虑锁定或写入其中的应用程序)
  • 这不适用于zvols
  • 您不应该拆分池并在不同的系统上使用它们(要小心故障转移情况

概括:

  • 如果您只关心磁盘上的一致性,那么您可以选择export -f完全关闭
  • 如果您关心所有数据,请使用sync=always快速 SSD
  • 将 iSCSI/NFS 视为 VM 的数据存储,本概述也可能有帮助(摘录:在来宾/VM 主机上使用 NFS 或禁用 iSCSI 写回缓存;在拍摄 ZFS 快照之前静默 VM,ZFS 无论如何都会很好,但来宾 VM 只会崩溃一致)

回复评论中的后续问题(遗漏了我没有任何有用答案的问题):

(1)“好消息/COW” - 如果顶级块即将更新怎么办 - 它总是会找到可用的顶级块(即使指向稍微旧版本的元数据树)?那会变得多糟糕?

最坏的情况是所有冗余设备上的超级块(位于所有其他块顶部的块)都损坏。因为它上面没有块,所以你无法从上面重建它,所以每个超级块都存在多个副本(IIRC 大约有 3 或 4 个),因此一个可能会丢失,但替换副本仍然存在。

(2) 我熟悉 TXG 并使用 ESXi。使用 APC UPS + 良好的 PSU/硬件 + P3700 NVMe ZIL,因此它具有不错的功率 + 快速 ZIL。但当前写入不太可能全部同步,正如您所说,sync=always 很慢。但你的回复确实引起了一个想法,我可能会做一些性能测试。我正在使用 dedup (节省 4 倍,值得),所以无论如何 write=slow (必须查找 DDT)。原因是sync=always仅影响由于DDT而无论如何都很慢的写入。但是设置sync=always会强制ZIL,ZIL非常快,这使得长TXGs安全,这可能意味着磁盘访问更高效。或者它可能会消除延迟。不知道是哪个!也许必须尝试一下!

我没有真正的重复数据删除经验,所以我不能在这里说任何有用的东西,除了你已经在硬件上做出了很好的选择(低延迟、高随机64k写入IOPS、NVMe接口)。如果您投资一些非常昂贵的永久 RAM 驱动器(ZeusRAM 等人),它只会更快。

(6) “磁盘上的一致性”是指 ZFS 很满意并且池是自洽的?不担心某些文件/目录。最终出现无效内容或未移动/删除 池突然消失,或者 zvol 上的 NTFWS/VMFS 等文件系统内部损坏(即作为 ZFS zvol 没问题,但从客户端角度来看,它需要 fsck/chkdsk)(提供池) ZFS 认为是安全/一致的

是的。本质上是“我的泳池没有搞砸,耶!”在多用户设置中 - 即使一个用户的文件出现问题,其他用户也不会受到影响。

(7) 通过“崩溃一致”,你的意思是我的意思吗(我想你是这样的)——ZFS 会很好,就 ZFS 而言,池会很好,但远程客户端的数据可能会与该客户端的数据相混淆。是否类似于客户端遇到突然的磁盘 IO 故障并且写入丢失? == 池没问题,客户端可能丢失/不一致的数据,可能需要帮助来恢复,就像任何其他磁盘 IO 故障或系统崩溃一样?

是的,本质上是虚拟机的硬关闭,而不是干净关闭,然后拍摄快照 - 如果您之后打开电源,fsck或者类似的取决于文件系统将运行,并且它可能会抱怨不干净关闭。这与 ESXi 快照形成鲜明对比,ESXi 快照在准确的时间点恢复,就好像什么也没发生一样,但它们需要与来宾系统交互(安装了来宾添加项)并包含虚拟机的虚拟内存。

您可以将两者结合起来发挥自己的优势:首先拍摄 ESXi 快照,然后拍摄数据存储的 ZFS 快照(ESXi 将其快照与虚拟机一起存储)。然后删除 ESXi 快照,但保留 ZFS 快照(由于块级副本,占用的空间要少得多)。恢复时,首先恢复 ZFS 快照,然后恢复到(保存的)ESXi 快照,然后您将从中断处恢复。 napp-it(带有 Web 界面的优秀 ZFS 管理系统)内置了这个概念(至少对于 NFS 数据存储,我没有检查 iSCSI,但假设它是类似的)。

相关内容