我在 Raspberry Pi 4 上运行带有 BTRFS 的 Manjaro ARM,该 Raspberry Pi 4 运行 SD 卡,众所周知,执行过多读/写操作时会出现问题。
出于这个原因,我想避免这样的操作,而不牺牲拥有实时快照的可能性,这是我运行 BTRFS 的唯一原因,这样我就可以将这些快照备份到其他地方。
我最近发现,使用 nodatacow 挂载选项挂载 BTRFS 子卷时可以有快照[1] [2],这会禁用 COW。我还知道,出于技术原因,必须在系统范围内提供此选项[3]。
根据我的理解,禁用 COW 意味着我们将获得“正常”文件系统的行为,期望元数据[4],这意味着文件内容总是会在新写入时被覆盖。然而,从我对[2],如果我们要执行快照,则保存每个文件的当前版本,同时为后续写入分配一个新位置,这将固有 nodatacow 并覆盖新写入,这意味着我将只有两个版本系统:当前版本和快照(可以像平常一样轻松恢复)。
进一步的缺点包括禁用校验和和压缩[3]。
我对当前问题的理解正确吗?
使用 nodatacow 挂载选项会对文件系统和快照的大小、碎片和性能(IO 操作)产生什么影响?
答案1
在研究与 btrfs 无关的东西时刚刚遇到这个问题。我想我可以回答你的一些问题:
nodatacow 如何影响 sd 卡上的实际碎片和性能?
不多。原因是,在合理的写入大小(尽可能接近擦除块大小)的情况下,fs 级 COW 将取代否则会发生的块设备级 COW。
当然,关键是了解 SD 卡的实际擦除块大小。但即使您的文件系统块大小小于介质的擦除块大小(通常是这种情况),您仍然可以获得相当好的性能。
请注意,块设备级 COW/动态磨损均衡(由 sd 卡中的控制器芯片完成)和 fs 级 COW 都会产生碎片,但这通常不被视为 sd 卡和 SSD 的问题因为它们缺乏寻道时间。
为什么擦除块大小对于就地写入很重要?
来自 raspi 论坛:https://forums.raspberrypi.com/viewtopic.php?t=11258
正如您所看到的,擦除块大小可能非常大(最多 16中号在该线程的示例中)。这意味着当您对 sd 卡进行就地 / nocow 写入时,该卡可能必须擦除 16M,然后最多写入 16M不管你写了多少数据。不过,这只是最糟糕的情况。之所以会发生这种情况,是因为 SD 卡和 SSD 中的控制器会尝试执行自己的 COW 版本来帮助实现磨损均衡,即它们将您写入的块重新映射到闪存介质中相对较少使用且之前已擦除的块。
由于 nodatacow,磁盘大小如何变化?
再说一遍,不多。无论如何,btrfs 的删除都是异步完成的,这意味着仅仅因为您删除了一个文件并不意味着磁盘上的空间可以立即用于其他用途。相反,另一个进程正在检查文件系统(普通卷和快照等)中引用数据的频率,并在计数达到 0 时将其删除。这对于 datacow 和 nodatacow 是相同的。您可能会发现的唯一区别是,如果您有一个非常忙于写入的非快照文件,并且同时您正在检查剩余的可用空间:您可能会注意到磁盘空间达到正确值的延迟更大值,因为受威胁且繁忙的文件可能会暂时使用比其实际包含的更多的媒体空间。
我推荐什么
使用noatime
挂载选项来最大限度地减少不必要的写入,确保分区与写入块大小正确对齐,如果它也与擦除块大小对齐(以避免写入放大),那就更好了,然后尝试一下。如果您使用相当标准的文件系统(繁忙的数据库和虚拟机映像除外),则很少需要对 SSD 和闪存介质进行所有其他优化。