![调整 ZFS 以实现突发顺序写入](https://linux22.com/image/776376/%E8%B0%83%E6%95%B4%20ZFS%20%E4%BB%A5%E5%AE%9E%E7%8E%B0%E7%AA%81%E5%8F%91%E9%A1%BA%E5%BA%8F%E5%86%99%E5%85%A5.png)
这是以下问题的后续:高速网络写入,大容量存储. 设置已发生明显变化。
我有一个池,其中raid-z2
有 6 个驱动器,全部是 Exos X18 CMR 驱动器。通过fio
手动测试,我知道该阵列平均可以维持大约 800 MB/s 的连续写入,这很好,并且符合该阵列的预期性能。该机器是 Ryzen5 Pro 2400 GE(4C/8T,3.8 GHz 加速),具有 32G ECC RAM、NVMe 启动/系统驱动器和 2x10Gbps 以太网端口(Intel x550-T2)。我正在运行最新的 Arch 系统,带有 zfs 2.1.2-1。
我的用例是一个视频档案,其中大部分是大型(约 30G)一次写入、一次读取、压缩的视频。我已禁用atime
、设置recordsize=1M
、设置compressios=off
和,dedup=off
因为数据实际上不可压缩,并且测试显示与compression=lz4
相比的性能更off
差,尽管互联网上说了,并且设计上没有重复数据。此池通过 Samba 在网络上共享。我已经调整了我的网络和 Samba,使从 Windows 计算机上的 NVMe NTFS 传输到 NVMe ext4 的速度达到 1GB/s,即相当接近用 9K 巨型帧饱和 10 Gbps 链路。
这是我遇到问题的地方。我希望能够以 1GB/s 的速度将整个 30G 视频档案传输到raid-z2
只能支持 800 MB/s 顺序写入的阵列。我的计划是使用基于 RAM 的脏页来吸收溢出,并在客户端传输“完成”后将其刷新到磁盘。我认为我所需要的只是(1024-800)*30~=7G
RAM 中的脏页,这些脏页可以在传输完成后约 10 秒内刷新到磁盘。我理解这对数据完整性的影响,并且风险是可以接受的,因为我总是可以在一个月内再次传输文件,以防断电导致文件丢失或不完整。
但是我无法让 ZFS 按照我期望的方式运行...我/etc/modprobe.d/zfs.conf
已像这样编辑了我的文件:
options zfs zfs_dirty_data_max_max=25769803776
options zfs zfs_dirty_data_max_max_percent=50
options zfs zfs_dirty_data_max=25769803776
options zfs zfs_dirty_data_max_percent=50
options zfs zfs_delay_min_dirty_percent=80
我已运行适当的mkinitcpio -P
命令来刷新我的 initramfs,并确认重新启动后设置已应用:
# arc_summary | grep dirty_data
zfs_dirty_data_max 25769803776
zfs_dirty_data_max_max 25769803776
zfs_dirty_data_max_max_percent 50
zfs_dirty_data_max_percent 50
zfs_dirty_data_sync_percent 20
即我将最大脏页设置为 24G,这比我需要的 7G 多得多,并且一直延迟写入,直到使用了 80%。据我所知,池应该能够将 19G 吸收到 RAM 中,然后才开始延迟从客户端 (Samba) 进行写入。
然而,我观察到从 Windows 客户端写入时,在写入速度约为 1 GB/s 的情况下,大约 16 秒后,写入性能急剧下降(iostat
仍然显示磁盘正在努力刷新数据),我只能假设这是 ZFS 写入节流的回推机制。然而,这毫无意义,因为至少即使在 16 秒内没有刷新任何内容,它也应该在 3 秒后恢复。此外,它在最后再次下降,见图:[ ][https://i.stack.imgur.com/Yd9WH.png]
我尝试过调整zfs_dirty_data_sync_percent
以更早开始写入,因为脏页缓冲区比默认值大得多,我还尝试过调整活动 io 缩放以zfs_vdev_async_write_active_{min,max}_dirty_percent
更早启动,以便使用较大的脏缓冲区更快地加快写入速度。这两种方法都只是稍微移动了悬崖的位置,但远没有达到我的预期。
问题:
- 我是否误解了写入限制延迟的工作原理?
- 我尝试做的事可行吗?
- 如果是这样,我做错了什么?
是的,我知道,我实际上只是在浪费几秒钟的时间,而且永远无法收回为实现这一目标所付出的努力。没关系,目前这是我和 ZFS 之间的个人问题,也是原则问题 ;)
答案1
您还需要将zfs_txg_timeout
参数从当前默认值 5 秒增加到 7G/0.2G/s = 35 秒左右,因此设置为 40 秒就足够了。
在你的/etc/modprobe.d/zfs.conf
:
options zfs zfs_txg_timeout=40
请注意,ARC 就是这样的“读取”缓存,与写入缓存没有任何关联,因此请确保您的 ARC 未设置为消耗块写入缓存必须吸收的每 30GB 写入流的额外 7G+ 数据。ZFS 的写入缓存与任何其他简单的块写入缓存(如commit
ext4 文件系统的参数)一样,因此请务必在非生产环境中进行测试,以确保在所有传输场景中都不会出现 RAM 不足的情况。
答案2
如果 zfs primarycache = all(默认),则每次写入都会更新 ARC。如果读取延迟对于您当前正在写入的数据并不重要,我建议设置 zfs primarycache=meta。
答案3
您目前没有足够的 RAM 或存储资源来满足您的要求。
围绕所需的 I/O 吞吐量水平及其最坏情况性能进行设计。
如果您需要在所有条件下为所述工作数据集提供 1GB/s 的吞吐量,则请确保磁盘主轴数或接口吞吐量能够支持这一点。