> For the complete documentation index, see [llms.txt](https://book.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://book.bsdcn.org/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.8.-gao-ji-zhu-ti.md).

# 23.8.高级主题

## 23.8.1. 调整

调整可调参数，使 ZFS 在不同的工作负载下表现最佳。FreeBSD 将 ZFS 内核可调参数作为 **sysctl(8)** 变量暴露在 `vfs.zfs` 下；**zfs(4)** 记录了每个可调参数及其默认值。需要在引导时生效的值设置在 **/boot/loader.conf** 中；运行时可调整的值用 **sysctl(8)** 调整，并在 **/etc/sysctl.conf** 中永久保存。

* `vfs.zfs.arc.max` - [ARC](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md) 的上限大小。默认值 `0` 让 ZFS 根据物理内存大小自动调整 ARC 大小。如果系统运行其他可能需要内存的守护进程或进程，请使用较小的值；参见 [ARC 大小与监控](#id-23.8.2.-arc-da-xiao-yu-jian-kong) 一节。可在运行时用 **sysctl(8)** 调整此值，并在 **/boot/loader.conf** 或 **/etc/sysctl.conf** 中设置。
* `vfs.zfs.arc.min` - [ARC](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md) 的下限大小。默认值 `0` 让 ZFS 自动选择一个较小的最小值。增大此值可防止其他应用程序挤出整个 ARC。可在运行时用 **sysctl(8)** 调整此值，并在 **/boot/loader.conf** 或 **/etc/sysctl.conf** 中设置。
* `vfs.zfs.arc.meta_balance` - [ARC](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md) 中缓存元数据与文件数据之间的平衡；值大于 `100` 时越来越倾向于元数据，默认值为 `500`。如果工作负载涉及对大量文件和目录的操作，或频繁的元数据操作，增大此值可以提高性能，但代价是较少的文件数据能适应 ARC。此可调参数替代了 OpenZFS 2.2 中移除的 `vfs.zfs.arc.meta_limit`。可随时通过 **sysctl(8)** 调整此值。
* `vfs.zfs.vdev.min_auto_ashift` - 池创建时自动使用的最低 `ashift`（扇区大小）。该值是 2 的幂。默认值 `9` 表示 `2^9 = 512`，即 512 字节的扇区大小。为了避免 *写放大* 并获得最佳性能，应将此值设置为池中设备使用的最大扇区大小。有关 4 KB 扇区驱动器上的池为何应使用 `ashift` 值 12 的说明，请参见 [创建和销毁存储池](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.3.-zpool-guan-li.md)。
* `vfs.zfs.prefetch.disable` - 禁用预取。值为 `0` 时启用，值为 `1` 时禁用。默认值为 `0`。预取通过将比请求的块更大的数据块读取到 [ARC](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md) 中，来期望稍后会需要这些数据。如果工作负载有大量随机读取，禁用预取可能会通过减少不必要的读取来提高性能。可随时通过 **sysctl(8)** 调整此值。
* `vfs.zfs.txg.timeout` - [事务组](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md) 之间的最大秒数。当前事务组写入池中，如果自上一个事务组以来经过了此时间，则启动新的事务组。如果写入了足够的数据，事务组可能会提前触发。默认值为 5 秒。较大的值可能会通过延迟异步写入来提高读取性能，但这可能导致写入事务组时性能不均匀。可随时通过 **sysctl(8)** 调整此值。
* `vfs.zfs.l2arc.write_max` - 限制每秒写入 [L2ARC](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md) 的数据量。此可调参数通过限制写入设备的数据量，延长 SSD 的使用寿命。可随时通过 **sysctl(8)** 调整此值。
* `vfs.zfs.l2arc.write_boost` - 将此可调参数的值添加到 `vfs.zfs.l2arc.write_max` 中，并在从 [L2ARC](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md) 驱逐第一个块之前，提升 SSD 的写入速度。这个“加速预热阶段”减少了重启后空 L2ARC 带来的性能损失。可随时通过 **sysctl(8)** 调整此值。
* `vfs.zfs.l2arc.rebuild_enabled` - 让 [L2ARC](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md) 的内容在重启后持久存在。默认值 `1` 让 ZFS 在导入池时根据缓存设备上存储的日志块重建 L2ARC，避免了空缓存原本需要的漫长预热期。将此值设置为 `0` 可始终从空的 L2ARC 开始。
* `vfs.zfs.vdev.max_active` - 池中每个设备上活跃 I/O 请求的上限数量。较高的值会保持设备命令队列满，从而可能提高吞吐量。较低的值则会减少延迟。可随时通过 **sysctl(8)** 调整此值。
* `vfs.zfs.vdev.*_min_active` 和 `vfs.zfs.vdev.*_max_active` - 调度器为每个 I/O 类别向每个设备发出的并发 I/O 请求的下限和上限数量：`sync_read`、`sync_write`、`async_read`、`async_write`、`scrub` 等。这些按类别的限制替代了旧版 ZFS 中基于延迟的 [scrub](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md) 和 [重新同步](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md) 节流。例如，增大 `vfs.zfs.vdev.scrub_max_active` 可让 scrub 使用每个设备队列的更大份额，更快完成，但代价是前台 I/O 延迟。
* `vfs.zfs.resilver_min_time_ms` - [重新同步](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md) 在事务组刷新之间工作的最短时间（以毫秒为单位）；默认值为 `3000`（3 秒）。当降级池面临丢失另一块设备的风险时，增大此值可更快完成重新同步，但代价是减慢正常的池操作。可随时通过 **sysctl(8)** 调整此值。

## 23.8.2. ARC 大小与监控

ZFS 将最近和频繁使用的数据和元数据保存在 RAM 中的 [ARC](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md) 中。ARC 按需增长直到 `vfs.zfs.arc.max`，并在其他程序需要内存时再次收缩，因此在专用存储服务器上，大部分 RAM 处于使用状态是正常的。ARC 以块在磁盘上的压缩形式存储它们，并在访问时解压。这种 *压缩 ARC* 让相同数量的 RAM 能缓存更多数据，提高了有效命中率。

**top(1)** 在其内存摘要行中显示当前 ARC 大小。`kstat.zfs.misc.arcstats` **sysctl(8)** 树暴露了详细的统计信息，包括当前大小、目标最大值以及命中和未命中计数器：

```sh
% sysctl kstat.zfs.misc.arcstats.size kstat.zfs.misc.arcstats.c_max kstat.zfs.misc.arcstats.hits kstat.zfs.misc.arcstats.misses
kstat.zfs.misc.arcstats.size: 8963041280
kstat.zfs.misc.arcstats.c_max: 15843122176
kstat.zfs.misc.arcstats.hits: 954912441
kstat.zfs.misc.arcstats.misses: 21356847
```

`filesystems/zfs-stats` Port 以人类可读的报告形式总结这些统计信息。

ARC 在内存压力下让出内存，但在 ZFS 与其他大型内存消费者（如数据库、虚拟机或 Jail）共享 RAM 的系统上，这种竞争可能导致双方性能不均匀。为 ARC 设置上限可为其他工作负载留下可预测的内存量。例如，要将 ARC 限制为 8 GB，将以下行添加到 **/boot/loader.conf**：

```ini
vfs.zfs.arc.max="8G"
```

用 **sysctl(8)** 更改 `vfs.zfs.arc.max` 会立即生效，不过收缩预热的 ARC 会逐步释放内存。

## 23.8.3. 同步写入、ZIL 与 SLOG

每个池都有一个 [ZIL](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md)。使用 **fsync(2)** 或 `O_SYNC` 标志请求同步语义的应用程序，在 ZFS 将相应的意图日志记录提交到稳定存储之前，不会收到确认。默认情况下，ZIL 位于池的常规 vdev 上，因此每个同步写入都会与正常的池 I/O 竞争。异步写入绕过 ZIL，并随下一个 [事务组](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md) 一起写入。

专用的 [日志](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md) vdev（通常称为 *SLOG*，即独立日志）将 ZIL 移到快速设备上：

```sh
# zpool add mypool log mirror nda0 nda1
```

SLOG 仅对产生大量同步写入的工作负载（如 NFS 服务器和数据库）有帮助。对纯异步工作负载没有影响。

几 GB 的 SLOG 容量就足够了：ZIL 最多保存几秒钟的传入写入（大约一个事务组的量），之后 ZFS 会将数据写入池中的最终位置。选择具有断电保护和低持续写入延迟的 SSD，并对日志设备进行镜像。ZFS 仅在崩溃后才读取 ZIL，因此如果未镜像的 SLOG 丢失同时伴随系统崩溃，会丢失那些已确认但未提交到池的写入。

`sync` 数据集属性控制同步写入行为：

* `sync=standard`（默认值）将同步写入提交到 ZIL，异步写入随下一个事务组写入。
* `sync=always` 将每个写入都视为同步写入，以性能换取安全性，仅对那些本应请求同步写入却未这样做的应用程序有帮助。
* `sync=disabled` 将每个写入都视为异步写入。

> **警告：** 使用 `sync=disabled` 时，ZFS 会在同步写入到达稳定存储之前就确认它们。池本身保持一致，但在崩溃或断电后，应用程序和 NFS 客户端会静默丢失最多几秒钟它们认为已安全写入的数据。不要对数据库、NFS 导出或任何其他重要数据使用 `sync=disabled`。

`logbias` 属性调整 ZFS 使用日志的方式：`logbias=latency`（默认值）倾向使用 SLOG 以最小化提交延迟，而 `logbias=throughput` 将同步数据直接写入主池，将 SLOG 容量保留给对延迟敏感的数据集。详见 **zfsprops(7)**。

## 23.8.4. 直接 I/O

> **注意：** 直接 I/O 需要 OpenZFS 2.3 或更高版本，首次出现在 FreeBSD 15.0 中。

`direct` 数据集属性控制 ZFS 如何处理使用 `O_DIRECT` 标志发出的请求：

* `direct=standard`（默认值）遵循 `O_DIRECT`：正确对齐的读取和写入绕过 [ARC](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.10.-zfs-te-xing-he-shu-yu.md)。
* `direct=always` 将每个正确对齐的读取或写入都视为直接请求。
* `direct=disabled` 静默忽略 `O_DIRECT`，并通过 ARC 处理每个请求。

直接 I/O 避免了 ARC 的内存复制和缓存开销。在由非常快的 NVMe 设备组成的池上，这种开销可能在 I/O 本身的成本中占主导地位，而维护自己缓存的应用程序（如数据库）会因为两次缓存相同数据而浪费 RAM。对于此类工作负载，直接 I/O 可以提高吞吐量并减少内存使用。

ZFS 仍然验证直接读取和写入的校验和，因此数据完整性保护不变。直接写入必须与数据集的 `recordsize` 对齐；ZFS 会静默地将请求中未对齐的部分重定向到 ARC。完整的对齐规则和限制详见 **zfsprops(7)**。

## 23.8.5. `recordsize` 与 `volblocksize`

`recordsize` 属性设置 ZFS 在数据集中存储文件所使用的最大块，默认为 128 KB。将块大小与工作负载的 I/O 模式匹配，可避免读取和写入超出应用程序请求的数据量。

对于执行小随机读取和写入的数据库，在创建数据库文件之前，将 `recordsize` 设置为数据库页面大小，通常为 8 KB 或 16 KB。对于存储大型媒体文件或备份流（顺序读取和写入）的数据集，`recordsize=1M` 可减少元数据开销并提高压缩率。卷使用 `volblocksize` 属性代替，默认为 16 KB，并且在创建卷后无法更改。

更改 `recordsize` 仅影响新写入的文件；现有文件保留其原始块大小。即使 `zfs rewrite` 也不会将新的 `recordsize` 应用于现有文件，因为影响逻辑块大小的属性更改对重写的块没有影响；需要重新复制文件才能用新值存储它们。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://book.bsdcn.org/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.8.-gao-ji-zhu-ti.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
