22.6.高级主题

22.6.1.优化

调整可优化的因素,可使 ZFS 在不同的工作负荷下都呈现最佳表现。

  • 13.x 使用 vfs.zfs.arc.max (12.x 使用 vfs.zfs.arc_max)——ARC 的上限大小。默认是 RAM 的总量减 1GB,或所有 RAM 的 5/8,以多者为准。如果系统上运行的任何其他守护程序或进程可能需要内存,请使用较低的值。在运行时用 sysctl(8) 调整此值,并在 /boot/loader.conf/etc/sysctl.conf 中设置它。

  • 13.x 使用 vfs.zfs.arc.meta_limit (12.x 使用 vfs.zfs.arc_meta_limit)——用于限制存储元数据的 ARC 的数量。默认是 vfs.zfs.arc_max 的四分之一。如果工作负载涉及对大量文件和目录的操作,或频繁的元数据操作,增加这个值将提高性能,代价是 ARC 中拟合的文件数据减少。在运行时用 /boot/loader.conf/etc/sysctl.conf 中的 sysctl(8) 调整此值。

  • 13.x 使用 vfs.zfs.arc.min (12.x 使用 vfs.zfs.arc_min)——ARC 的最小大小。默认是 vfs.zfs.arc_meta_limit 的一半。调整此值以防止其他应用程序压榨出整个 ARC。在运行时用 sysctl(8)/boot/loader.conf/etc/sysctl.conf 来调整此值。

  • vfs.zfs.vdev.cache.size——预先分配的内存量,作为池中每个设备的缓存。使用的总内存量将是这个值乘以设备的数量。在启动时或 /boot/loader.conf 中设置此值。

  • vfs.zfs.min_auto_ashift——在创建池时自动使用的较低 ashift(扇区大小)。该值是二的幂值。默认值 9 代表 2^9=512,即扇区大小为 512 字节。为了避免写入放大并获得最佳性能,将此值设置为池中设备使用的最大扇区大小。

    普通磁盘的扇区是 4KB。在这些磁盘上使用默认的 9 作为 ashift 会导致这些设备的写入放大。单个 4KB 的写入所包含的数据被写成 8 个 512 字节的写入。在创建池时,ZFS 试图从所有设备中读取本地扇区大小,但具有 4 KB 扇区的驱动器报告说它们的扇区是 512 字节,以实现兼容。在创建池之前,将 vfs.zfs.min_auto_ashift 设置为 122^12=4096),迫使 ZFS 在这些磁盘上使用 4KB 块以获得最佳性能。

    强制 4KB 区块对于有计划的磁盘升级的池也很有用。未来的磁盘使用 4KB 扇区,而且在创建池后,ashift 值不能改变。

    在一些特定的情况下,较小的 512 字节的块大小可能是更好的。当使用 512 字节的磁盘用于数据库或作为虚拟机的存储时,在小的随机读取过程中传输的数据较少。这可以在使用较小的 ZFS 记录大小时提供更好的性能。

  • vfs.zfs.prefetch_disable——禁用预取。值为 0 时启用,1 时停用。默认值是 0,除非系统的内存小于 4GB。预取的作用是将比请求的更大的块读入 ARC,希望很快就能需要这些数据。如果工作负载有大量的随机读取,禁用预取实际上可能会通过减少不必要的读取来提高性能。在任何时候都可以用 sysctl(8) 调整此值。

  • vfs.zfs.vdev.trim_on_init——控制添加到池中的新设备是否对其运行 TRIM 命令。这可以确保 SSD 的最佳性能和寿命,但需要消耗额外的时间。如果设备已经被安全擦除,禁用此设置将使新设备的添加更快。在任何时候都可用 sysctl(8) 调整此值。

  • vfs.zfs.vdev.max_pending——限制每个设备的挂起 I/O 请求的数量。一个较高的值会使设备的命令队列保持满员,并可能带来更高的吞吐量。一个较低的值将减少延迟。在任何时候都可以用 sysctl(8) 调整此值。

  • vfs.zfs.top_maxinflight——每个顶层 vdev 的未完成 I/O 的最高数量。限制命令队列的深度以防止高延迟。这个限制是每个顶级 vdev 的,意味着这个限制独立地适用于每个 镜像RAID-Z 或其他 vdev。在任何时候都可以用 sysctl(8) 来调整此值。

  • vfs.zfs.l2arc_write_max——限制每秒写入 L2ARC 的数据量。这个调节器通过限制写入设备的数据量来延长 SSD 的寿命。在任何时候都可以用 sysctl(8) 调整此值。

  • vfs.zfs.l2arc_write_boost——在 vfs.zfs.l2arc_write_max 的基础上增加这个可调控的值,并增加对 SSD 的写入速度,直到驱逐 L2ARC 的第一个块。这个“涡轮增压热身阶段”可以减少重启后空的 L2ARC 带来的性能损失。在任何时候都可以用 sysctl(8) 调整此值。

  • vfs.zfs.scrub_delay——在 scrub 过程中,每个 I/O 之间延迟的刻度数。为了确保 scrub 不干扰池的正常运行,如果有任何其他 I/O 正在发生,scrub 将在每个命令之间延迟。这个值控制 scrub 所产生的总 IOPS(每秒 I/O 数)的限制。设置的颗粒度由 kern.hz 的值决定,默认为每秒 1000 次。改变这个设置会导致不同的有效 IOPS 限制。默认值是 4,导致的限制是: 1000 ticks/sec / 4 = 250 IOPS。使用一个 20 的值会得到一个限制: 1000 ticks/sec / 20 = 50 IOPS。池子上的最近活动限制 scrub 的速度,这由 vfs.zfs.scan_idle 决定。在任何时候都可以用 sysctl(8) 调整此值。

  • vfs.zfs.resilver_delay——在 resilver 过程中每次 I/O 之间插入延迟的毫秒数量。为了确保 resilver 不会干扰池的正常运行,如果有任何其他 I/O 正在发生,resilver 将在每个命令之间延迟。这个值控制 resilver 产生的总 IOPS(每秒 I/O 数)的限制。ZFS 通过 kern.hz 的值来决定设置的粒度,其默认值为每秒 1000 次。改变这个设置会导致不同的有效 IOPS 限制。默认值是 2,导致的限制是: 1000 ticks/sec / 2 = 500 IOPS。如果另一个设备失败可能导致池 Fault,导致数据丢失,那么将池返回到 Online 状态可能更为重要。一个 0 值将给予 resilver 操作与其他操作相同的优先级,加速 resilver 过程。池上的其他最近活动限制 resilver 的速度,由 vfs.zfs.scan_idle 决定。在任何时候都可以用 sysctl(8) 调整此值。

  • vfs.zfs.scan_idle——在考虑池是空闲的之前,从最后一次操作开始的毫秒数量。当池子处于空闲状态时,ZFS 会禁用 scrubresilver 的速率限制。在任何时候都可以用 sysctl(8) 调整此值。

  • vfs.zfs.txg.timeout——事务组之间的最高秒数。当前的事务组将写入池中,如果从上一个事务组开始已经过这个时间,就会启动一个新的事务组。如果写入足够的数据,事务组可能会提前触发。默认值是 5 秒。一个更大的值可能会通过延迟异步写入来提高读取性能,但这可能会导致写入事务组时的性能不均衡。在任何时候都可以用 sysctl(8) 调整此值。

22.6.2.i386 上的 ZFS

ZFS 提供的一些功能是内存密集型的,可能需要在内存有限的系统上进行优化以提高效率。

22.6.2.1.内存

作为一个较低的值,总的系统内存应该至少是 1GB。推荐的内存数量取决于池的大小和 ZFS 使用的功能。一般的经验法则是每 1TB 的存储量需要使用 1GB 的内存。如果使用重复数据删除功能,一般的经验法则是每 TB 存储使用 5 GB 内存进行重复数据删除。虽然有些用户使用的 ZFS 内存更少,但负载过重的系统可能会因为内存耗尽而 panic。ZFS 可能需要对低于推荐内存要求的系统进行进一步的优化。

22.6.2.2.内核配置

由于 i386™ 平台的地址空间限制,i386™ 架构上的 ZFS 用户必须在定制内核配置文件中加入这个选项,重新编译内核,然后重新启动:

options        KVA_PAGES=512

这就扩展了内核地址空间,允许 vm.kvm_size 可调值超过 1GB 的强制限制,或者 PAE 的 2GB 限制。为了找到这个选项的最合适的值,将所需的地址空间(以 MB 为单位)除以 4。在这个例子中,512 代表 2GB。

22.6.2.3.引导器的可优化选项

在所有的 FreeBSD 架构上增加 kmem 地址空间。在 /boot/loader.conf 中加入以下选项,然后重新启动,一个拥有 1GB 物理内存的测试系统就会从中受益:

vm.kmem_size="330M"
vm.kmem_size_max="330M"
vfs.zfs.arc.max="40M"
vfs.zfs.vdev.cache.size="5M"

关于 ZFS 相关优化的更详细的建议列表,请参见 https://wiki.freebsd.org/ZFSTuningGuide

最后更新于

FreeBSD 中文社区