李守中

ZFS 踩坑与优化

Table of Contents

1 ZFS Volume 不能作为 SWAP

使用 zvol 来创建 swap 可能会导致操作系统死锁。详见 https://github.com/openzfs/zfs/issues/7734

直到 2023 年这个 Bug 还没有修好。

2 ZFS Pool scrub 后 error 没有消失

执行 zpool scrub mymir1 进行全盘数据校验,校验过程中查看 zpool status -xv 是这样的:

  pool: mymir1
 state: ONLINE
status: One or more devices has experienced an error resulting in data
        corruption.  Applications may be affected.
action: Restore the file in question if possible.  Otherwise restore the
        entire pool from backup.
   see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-8A
  scan: scrub in progress since Mon Aug  9 11:45:14 2021
        1.62T scanned at 213M/s, 1.56T issued at 206M/s, 6.97T total
        0B repaired, 22.36% done, 07:40:10 to go
config:

        NAME        STATE     READ WRITE CKSUM
        mymir1      ONLINE       0     0     0
          da2       ONLINE       0     0     0

errors: Permanent errors have been detected in the following files:

        <metadata>:<0x0>
        <metadata>:<0x3d>

这个池按照 scrub -> export -> import -> scrub -> export -> import 流程走一遍。第一个 scrub 修文件,第二个 scrub 执行后 zfs 检测不到错误 errors 就没有了。

跟据 Richard Elling 的说法: zpool statuserror buffer 包含最近两个 scrub 的结果信息。

因此,在删除异常的对象 ( 比如文件 ) 后,它仍然被列在错误缓冲区中。这时候用 zdb 查找 dataset+object tuple 找不到任何内容。所以要用两次 scrub 完全更新 error buffer 后, zpool status 才不会报错。

3 NFS 客户端以 sync I/O 的方式向 ZFS 写入数据时性能差

客户端通过 NFSv3 向 NFS 服务端的 ZFS 文件系统以 sync I/O 的方式写入数据时速度只有 18 MB/s,但内网速度是千兆,这速度显然没跑满网络带宽。

3.1 关闭 ZFS 的 sync I/O

在 NFS 服务器上执行 zfs get sync 可以看到所有 zfs 文件系统使用了 async 还是 sync:

NAME                PROPERTY  VALUE     SOURCE
mymir2              sync      standard  default
mymir2/data         sync      standard  default
mymir2/videos       sync      standard  default

sync 属性的取值可以为:

  • standard: 默认值,是否同步取决于写操作请求。
  • always: 强制同步,高安全,低性能。
  • disable: 不同步,高性能,低安全。

数据读写方式为 sync只有要写入的数据数据被真正地写入硬盘之后,才会返回写入成功信号 ,这就是问题所在。

执行 zfs set sync=disabled <zpool_name>/<zpool_zfs> 可以将 sync 模式关闭。

比如 zfs set sync=disabled mymir2/data 让 I/O 异步执行,速度就变快了。再执行 zfs get sync 可以看到:

NAME                PROPERTY  VALUE     SOURCE
mymir2              sync      standard  default
mymir2/data         sync      disabled  local
mymir2/videos       sync      standard  default

此时数据传输速度可以到相对正常的 70 MB/s 左右,在 50 - 77 MB/s 波动。

数据传输完毕建议把 I/O 方式改回 sync,毕竟异步读写的方式不是那么安全。

执行 sudo zfs set sync=standard <zpool_name>/<zpool_zfs> 可以恢复默认的 sync 模式。

比如,执行 sudo zfs set sync=standard mymir2/data 后再执行 zfs get sync 可以看到:

NAME                PROPERTY  VALUE     SOURCE
mymir2              sync      standard  default
mymir2/data         sync      standard  local
mymir2/videos       sync      standard  default

如果想把 SOURCE 字段也恢复原样,需要执行 sudo zfs inherit -rS sync <zpool_name>/<zpool_zfs> ,比如 sudo zfs inherit -rS sync mymir2/datamymir2/datasync 属性从父路径继承。再执行 zfs get sync 可以看到:

NAME                PROPERTY  VALUE     SOURCE
mymir2              sync      standard  default
mymir2/data         sync      standard  default
mymir2/videos       sync      standard  default

3.2 给 zpool 加独立 ZIL ( SLOG 组件 )

ZIL 和 SLOG 的描述可以读本站的 ZFS ZIL(SLOG) 组件 一文。

用于 ZIL 的设备应该是可以高速读写的 SSD,使用 4K 读写速度低下的 HDD 作为 ZIL 可能会降低整个 zpool 的性能。后文用 SLOG 设备 指代 具有 ZIL 功能的独立设备或分区

3.2.1 给没有 SLOG 设备的池添加一个 SLOG 设备

执行 zpool add <zpool_name> log <device> 可以为 <zpool_name> 添加 SLOG 设备,比如执行 zpool add mymir2 log /dev/da6p2

% zpool status
  pool: mymir2
 state: ONLINE
status: One or more devices is currently being resilvered.  The pool will
        continue to function, possibly in a degraded state.
action: Wait for the resilver to complete.
  scan: resilver in progress since Sun Sep 19 17:58:44 2021
        467G scanned at 46.7G/s, 467G issued at 46.7G/s, 2.58T total
        0B resilvered, 17.70% done, 00:00:46 to go
config:

        NAME        STATE     READ WRITE CKSUM
        mymir2      ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            da4     ONLINE       0     0     0
            da5     ONLINE       0     0     0

errors: No known data errors
% zpool add mymir2 log /dev/da6p2
% zpool status
  pool: mymir2
 state: ONLINE
status: One or more devices is currently being resilvered.  The pool will
        continue to function, possibly in a degraded state.
action: Wait for the resilver to complete.
  scan: resilver in progress since Sun Sep 19 17:58:44 2021
        467G scanned at 46.7G/s, 467G issued at 46.7G/s, 2.58T total
        0B resilvered, 17.70% done, 00:00:46 to go
config:

        NAME        STATE     READ WRITE CKSUM
        mymir2      ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            da4     ONLINE       0     0     0
            da5     ONLINE       0     0     0
        logs
          da6p1   ONLINE       0     0     0

errors: No known data errors

3.2.2 向已有一个 SLOG 设备的池添加另一个 SLOG 设备使之互为镜像

执行 zpool attach <zpool_name> <log_device> <device> 可以为 <zpool_name> 这个 pool 的 SLOG 设备创建镜像,比如 zpool attach mymir2 da6p2 /dev/da6p1:

% zpool status
  pool: mymir2
 state: ONLINE
status: One or more devices is currently being resilvered.  The pool will
        continue to function, possibly in a degraded state.
action: Wait for the resilver to complete.
  scan: resilver in progress since Sun Sep 19 17:58:44 2021
        467G scanned at 46.7G/s, 467G issued at 46.7G/s, 2.58T total
        0B resilvered, 17.70% done, 00:00:46 to go
config:

        NAME        STATE     READ WRITE CKSUM
        mymir2      ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            da4     ONLINE       0     0     0
            da5     ONLINE       0     0     0
        logs
          da6p1   ONLINE       0     0     0

errors: No known data errors
% zpool add mymir2 log /dev/da6p2
% zpool status
  pool: mymir2
 state: ONLINE
status: One or more devices is currently being resilvered.  The pool will
        continue to function, possibly in a degraded state.
action: Wait for the resilver to complete.
  scan: resilver in progress since Sun Sep 19 17:58:44 2021
        467G scanned at 46.7G/s, 467G issued at 46.7G/s, 2.58T total
        0B resilvered, 17.70% done, 00:00:46 to go
config:

        NAME        STATE     READ WRITE CKSUM
        mymir2      ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            da4     ONLINE       0     0     0
            da5     ONLINE       0     0     0
        logs
          mirror-1  ONLINE       0     0     0
            da6p2   ONLINE       0     0     0
            da6p1   ONLINE       0     0     0

errors: No known data errors

3.2.3 直接添加两个互为镜像的 SLOG 设备

执行 zpool add <zpool_name> log mirror <device_a> <device_b> 可以为 <zpool_name> 这个 pool 添加 SLOG 设备,并让两个设备互为镜像,比如 zpool add mymir2 log mirror /dev/da6p1 /dev/da6p2



Last Update: 2023-06-08 Thu 16:15

Contact: [email protected]     Generated by: Emacs 27.1 (Org mode 9.3)

若正文中无特殊说明,本站内容遵循: 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议