为什么 Linux 上的 ZFS 无法充分利用 AWS i2.8xlarge 实例上的 8x SSD?

ane*_*son 12 zfs amazon-web-services zfsonlinux

我对 ZFS 完全陌生,所以一开始我想我会对它做一些简单的基准测试,以了解它的行为方式。我想突破它的性能极限,所以我配置了一个 Amazon EC2i2.8xlarge实例(几乎 7 美元/小时,时间就是金钱!)。此实例有 8 个 800GB SSD。

fio对 SSD 本身进行了测试,并得到以下输出(已修剪):

$ sudo fio --name randwrite --ioengine=libaio --iodepth=2 --rw=randwrite --bs=4k --size=400G --numjobs=8 --runtime=300 --group_reporting --direct=1 --filename=/dev/xvdb
[trimmed]
  write: io=67178MB, bw=229299KB/s, iops=57324, runt=300004msec
[trimmed]
Run Code Online (Sandbox Code Playgroud)

57K IOPS 用于 4K 随机写入。可敬。

然后我创建了一个跨越所有 8 个的 ZFS 卷。起初我有一个raidz1包含所有 8 个 SSD 的 vdev,但我读到了这对性能不利的原因,所以我最终得到了四个mirrorvdev,如下所示:

$ sudo zpool create testpool mirror xvdb xvdc mirror xvdd xvde mirror xvdf xvdg mirror xvdh xvdi
$ sudo zpool list -v
NAME   SIZE  ALLOC   FREE  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
testpool  2.91T   284K  2.91T         -     0%     0%  1.00x  ONLINE  -
  mirror   744G   112K   744G         -     0%     0%
    xvdb      -      -      -         -      -      -
    xvdc      -      -      -         -      -      -
  mirror   744G    60K   744G         -     0%     0%
    xvdd      -      -      -         -      -      -
    xvde      -      -      -         -      -      -
  mirror   744G      0   744G         -     0%     0%
    xvdf      -      -      -         -      -      -
    xvdg      -      -      -         -      -      -
  mirror   744G   112K   744G         -     0%     0%
    xvdh      -      -      -         -      -      -
    xvdi      -      -      -         -      -      -
Run Code Online (Sandbox Code Playgroud)

我将记录大小设置为 4K 并运行我的测试:

$ sudo zfs set recordsize=4k testpool
$ sudo fio --name randwrite --ioengine=libaio --iodepth=2 --rw=randwrite --bs=4k --size=400G --numjobs=8 --runtime=300 --group_reporting --filename=/testpool/testfile --fallocate=none
[trimmed]
  write: io=61500MB, bw=209919KB/s, iops=52479, runt=300001msec
    slat (usec): min=13, max=155081, avg=145.24, stdev=901.21
    clat (usec): min=3, max=155089, avg=154.37, stdev=930.54
     lat (usec): min=35, max=155149, avg=300.91, stdev=1333.81
[trimmed]
Run Code Online (Sandbox Code Playgroud)

我在此 ZFS 池上仅获得 52K IOPS。这实际上比一个 SSD 本身略差。

我不明白我在这里做错了什么。我是否错误地配置了 ZFS,或者这是对 ZFS 性能的糟糕测试?

请注意,我使用的是官方的 64 位 CentOS 7 HVM 映像,但我已升级到 4.4.5 elrepo 内核:

$ uname -a
Linux ip-172-31-43-196.ec2.internal 4.4.5-1.el7.elrepo.x86_64 #1 SMP Thu Mar 10 11:45:51 EST 2016 x86_64 x86_64 x86_64 GNU/Linux
Run Code Online (Sandbox Code Playgroud)

我从此处列出的 zfs 存储库安装了 ZFS 。我有 0.6.5.5 版本的zfs包。

UPDATE:每@ ewwhite的建议,我想ashift=12ashift=13

$ sudo zpool create testpool mirror xvdb xvdc mirror xvdd xvde mirror xvdf xvdg mirror xvdh xvdi -o ashift=12 -f
Run Code Online (Sandbox Code Playgroud)

$ sudo zpool create testpool mirror xvdb xvdc mirror xvdd xvde mirror xvdf xvdg mirror xvdh xvdi -o ashift=13 -f
Run Code Online (Sandbox Code Playgroud)

这些都没有任何区别。据我所知,最新的 ZFS 位足够智能,可以识别 4K SSD 并使用合理的默认值。

然而,我确实注意到 CPU 使用率正在飙升。@Tim 提出了这个建议,但我驳回了它,但是我认为我看 CPU 的时间不够长,无法注意到。此实例上大约有 30 个 CPU 内核,CPU 使用率高达 80%。饥饿的过程? z_wr_iss,很多这样的例子。

我确认压缩已关闭,所以它不是压缩引擎。

我没有使用raidz,所以它不应该是奇偶计算。

我做了一个perf top,它显示了在_raw_spin_unlock_irqrestoreinz_wr_int_4osq_lockin 中花费的大部分内核时间z_wr_iss

我现在相信这个性能瓶颈有一个 CPU 组件,尽管我还没有弄清楚它可能是什么。

更新 2:根据 @ewwhite 和其他人的建议,即这种环境的虚拟化性质造成了性能不确定性,我曾经fio对分布在环境中四个 SSD 上的随机 4K 写入进行基准测试。每个 SSD 本身提供约 55K IOPS,所以我预计其中四个大约有 240K IO。这或多或少是我得到的:

$ sudo fio --name randwrite --ioengine=libaio --iodepth=8 --rw=randwrite --bs=4k --size=398G --numjobs=8 --runtime=300 --group_reporting --filename=/dev/xvdb:/dev/xvdc:/dev/xvdd:/dev/xvde
randwrite: (g=0): rw=randwrite, bs=4K-4K/4K-4K/4K-4K, ioengine=libaio, iodepth=8
...
randwrite: (g=0): rw=randwrite, bs=4K-4K/4K-4K/4K-4K, ioengine=libaio, iodepth=8
fio-2.1.5
Starting 8 processes
[trimmed]
  write: io=288550MB, bw=984860KB/s, iops=246215, runt=300017msec
    slat (usec): min=1, max=24609, avg=30.27, stdev=566.55
    clat (usec): min=3, max=2443.8K, avg=227.05, stdev=1834.40
     lat (usec): min=27, max=2443.8K, avg=257.62, stdev=1917.54
[trimmed]
Run Code Online (Sandbox Code Playgroud)

这清楚地表明,虽然虚拟化的环境可以维持比我所看到的高得多的 IOPS。ZFS 实现方式的某些方面使其无法达到最高速度。我就是想不通那是什么。

eww*_*ite 6

这个设置可能没有很好地调整。使用 SSD 时,/etc/modprobe/zfs.conf 文件和 ashift 值都需要参数

尝试 ashift=12 或 13 并再次测试。


编辑:

这仍然是一个虚拟化的解决方案,所以我们对底层硬件或一切是如何互连的了解不多。我不知道您会从此解决方案中获得更好的性能。


编辑:

我想我没有看到尝试以这种方式优化云实例的意义。因为如果以最高性能为目标,您就会使用硬件,对吗?

但请记住,ZFS 有很多可调设置,并且默认情况下您获得的设置与您的用例并不接近。

在您的/etc/modprobe.d/zfs.conf并重新启动中尝试以下操作。这是我在应用服务器的全 SSD 数据池中使用的。您的 ashift 应该是 12 或 13。使用compression=off 进行基准测试,但在生产中使用compression=lz4。设置时间=关闭。我将记录大小保留为默认值(128K)。

options zfs zfs_vdev_scrub_min_active=48
options zfs zfs_vdev_scrub_max_active=128
options zfs zfs_vdev_sync_write_min_active=64
options zfs zfs_vdev_sync_write_max_active=128
options zfs zfs_vdev_sync_read_min_active=64
options zfs zfs_vdev_sync_read_max_active=128
options zfs zfs_vdev_async_read_min_active=64
options zfs zfs_vdev_async_read_max_active=128
options zfs zfs_top_maxinflight=320
options zfs zfs_txg_timeout=30
options zfs zfs_dirty_data_max_percent=40
options zfs zfs_vdev_scheduler=deadline
options zfs zfs_vdev_async_write_min_active=8
options zfs zfs_vdev_async_write_max_active=64
options zfs zfs_prefetch_disable=1
Run Code Online (Sandbox Code Playgroud)