ZFS 池缓慢顺序读取

ZFS 池缓慢顺序读取

我有一个与此问题相关的问题,但它太复杂太大了,所以我决定将问题分为 NFS 问题和本地问题。我也尝试在 zfs-discuss 邮件列表中询问此问题,但没有成功。

同一服务器上的 NFS/CIFS 目录之间复制速度缓慢

概要:我的设置以及我的期望

  1. 我有一个包含 4 个磁盘的 ZFS 池。2TB RED 配置为 2 个镜像,这些镜像是条带化的 (RAID 10)。在 Linux 上,zfsonlinux。没有缓存或日志设备。
  2. 数据在镜像之间保持平衡(对 ZFS 来说很重要)
  3. 每个磁盘可以以 147MB/秒的速度并行读取(原始 w/dd),从而产生 588MB/秒的综合吞吐量。
  4. 根据类似 4TB RED 磁盘的基准测试,我预计每个磁盘的写入速度约为 115MB/秒,读取速度约为 138MB/秒,重写速度约为 50MB/秒。我预计读取或写入速度不会低于 100MB/秒,因为现在任何磁盘都可以做到这一点。
  5. 我认为在负载下读取或写入顺序数据时,所有 4 个磁盘的 IO 利用率都会达到 100%。并且磁盘在 100% 利用率下的输出速度将超过 100MB/秒。
  6. 我以为这个池会给我带来比单个磁盘大约 2 倍的写入、2 倍的重写和 4 倍的读取性能 -我错了吗?
  7. 新的我认为同一池上的 ext4 zvol 的速度与 ZFS 大致相同

我实际得到的

我发现池的读取性能并不像我预期的那么高

邦尼++几天前的游泳池基准测试

版本 1.97 ------顺序输出------ --顺序输入- --随机-
并发 1 -每个 Chr- --块-- -重写- -每个 Chr- --块-- --查找--
机器大小 K/秒 %CP K/秒 %CP K/秒 %CP K/秒 %CP K/秒 %CP /秒 %CP
伊戈尔 63G 99 99 232132 47 118787 27 336 97 257072 22 92.7 6

邦尼++在 zpool 中单独的一个 4TB RED 驱动器上

版本 1.97 ------顺序输出------ --顺序输入- --随机-
并发 1 -每个 Chr- --块-- -重写- -每个 Chr- --块-- --查找--
机器大小 K/秒 %CP K/秒 %CP K/秒 %CP K/秒 %CP K/秒 %CP /秒 %CP
伊戈尔 63G 101 99 115288 30 49781 14 326 97 138250 13 111.6 8

根据这个结果,基于单个 4TB RED 驱动器的结果,读取和重写速度是合适的(它们是两倍)。但是,我预期的读取速度约为 550MB/秒(4TB 驱动器速度的 4 倍),我至少希望达到 400MB/秒左右。相反,我看到的是大约 260MB/秒

邦尼++从刚才开始关注游泳池,同时收集以下信息。与以前不太一样,没有任何变化。

版本 1.97 ------顺序输出------ --顺序输入- --随机-
并发 1 -每个 Chr- --块-- -重写- -每个 Chr- --块-- --查找--
机器大小 K/秒 %CP K/秒 %CP K/秒 %CP K/秒 %CP K/秒 %CP /秒 %CP
伊戈尔 63G 103 99 207518 43 108810 24 342 98 302350 26 256.4 18

zpool iostat写入期间。对我来说似乎没问题。

                                                 容量操作带宽
池分配空闲读写读写
-------------------------------------------- ----- ----- ----- ----- ----- -----
池2 1.23T 2.39T 0 1.89K 1.60K 238M
  镜像 631G 1.20T 0 979 1.60K 120M
    ata-WDC_WD20EFRX-68AX9N0_WD-WMC300004469 - - 0 1007 1.60K 124M
    ata-WDC_WD20EFRX-68EUZN0_WD-WCC4MLK57MVX - - 0 975 0 120M
  镜像 631G 1.20T 0 953 0 117M
    ata-WDC_WD20EFRX-68AX9N0_WD-WCC1T0429536 - - 0 1.01K 0 128M
    ata-WDC_WD20EFRX-68EUZN0_WD-WCC4M0VYKFCE - - 0 953 0 117M

zpool iostat重写期间。我觉得没问题,我认为

                                                 容量操作带宽
池分配空闲读写读写
-------------------------------------------- ----- ----- ----- ----- ----- -----
池2 1.27T 2.35T 1015 923 125M 101M
  镜像 651G 1.18T 505 465 62.2M 51.8M
    ata-WDC_WD20EFRX-68AX9N0_WD-WMC300004469 - - 198 438 24.4M 51.7M
    ATA-WDC_WD20EFRX-68EUZN0_WD-WCC4MLK57MVX - - 306 384 37.8M 45.1M
  镜像 651G 1.18T 510 457 63.2M 49.6M
    ata-WDC_WD20EFRX-68AX9N0_WD-WCC1T0429536 - - 304 371 37.8M 43.3M
    ata-WDC_WD20EFRX-68EUZN0_WD-WCC4M0VYKFCE - - 206 423 25.5M 49.6M

我很好奇发生了什么事

zpool iostat在读取期间

                                                 容量操作带宽
池分配空闲读写读写
-------------------------------------------- ----- ----- ----- ----- ----- -----
池2 1.27T 2.35T 2.68K 32 339M 141K
  镜像 651G 1.18T 1.34K 20 169M 90.0K
    ata-WDC_WD20EFRX-68AX9N0_WD-WMC300004469 - - 748 9 92.5M 96.8K
    ata-WDC_WD20EFRX-68EUZN0_WD-WCC4MLK57MVX - - 623 10 76.8M 96.8K
  镜像 651G 1.18T 1.34K 11 170M 50.8K
    ata-WDC_WD20EFRX-68AX9N0_WD-WCC1T0429536 - - 774 5 95.7M 56.0K
    ata-WDC_WD20EFRX-68EUZN0_WD-WCC4M0VYKFCE - - 599 6 74.0M 56.0K

iostat -x在同一读取操作期间。请注意 IO % 并非为 100%。

设备:rrqm/s wrqm/sr/sw/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
平均存款 0.60 0.00 661.30 6.00 83652.80 49.20 250.87 2.32 3.47 3.46 4.87 1.20 79.76
平均数 0.80 0.00 735.40 5.30 93273.20 49.20 251.98 2.60 3.51 3.51 4.15 1.20 89.04
自发性密度 0.50 0.00 656.70 3.80 83196.80 31.20 252.02 2.23 3.38 3.36 6.63 1.17 77.12
平均日均值 0.70 0.00 738.30 3.30 93572.00 31.20 252.44 2.45 3.33 3.31 7.03 1.14 84.24

zpool 和测试数据集设置:

  • atime 已关闭
  • 压缩已关闭
  • ashift 为 0(自动检测 - 我的理解是这没问题)
  • zdb 说磁盘都是 ashift=12
  • 模块 - 选项 zfs zvol_threads=32 zfs_arc_max=17179869184
  • 同步 = 标准

编辑 - 2015 年 10 月 30 日

我做了更多测试

  • 数据集 bonnie++ w/recordsize=1M = 写入 226MB,读取 392MB好多了
  • 数据集 dd,记录大小=1M = 写入 260MB,读取 392MB好多了
  • zvol w/ext4 dd bs=1M = 写入 128MB,读取 107MB为什么这么慢?
  • 数据集 2 进程并行 = 227MB 写入,396MB 读取
  • dd direct io 对数据集和 zvol 没有影响

我对增加记录大小后的性能感到满意。池中的几乎每个文件都远远超过 1MB。所以我就保持原样。磁盘仍然没有达到 100% 的利用率,这让我怀疑它是否还能更快。现在我想知道为什么 zvol 性能如此糟糕,因为这是我(偶尔)使用的东西。

我很乐意提供评论/答案中要求的任何信息。我​​的另一个问题中也发布了大量信息:同一服务器上的 NFS/CIFS 目录之间复制速度缓慢

我完全明白我可能只是不明白某些事情,而这可能根本不是问题。提前致谢。

为了清楚起见,问题是:为什么 ZFS 池没有我预期的那么快?也许还有其他问题?

答案1

我设法使速度非常接近我预期的数字。

我在寻找400MB/秒并管理392MB/秒。所以我说问题解决了。后来我又加了一个缓存设备,我成功了458MB/秒读取(我相信是缓存的)。

1.最初,只需将 ZFS 数据集recordsize值增加到1M

zfs set recordsize=1M pool2/test

我相信这种改变只会减少磁盘活动,从而提高大型同步读写的效率。这正是我想要的。

变更后的结果

  • bonnie++ = 写入 226MB,读取 392MB
  • dd = 写入 260MB,读取 392MB
  • 2 个进程并行 = 227MB 写入,396MB 读取

2.当我添加缓存设备(120GB SSD)时,情况变得更好了。写入速度稍慢,我不知道为什么。

Version  1.97       ------Sequential Output------ --Sequential Input- --Random-
Concurrency   1     -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
Machine        Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP  /sec %CP
igor            63G           208325  48 129343  28           458513  35 326.8  16

缓存设备的诀窍是l2arc_noprefetch=0设置/etc/modprobe.d/zfs.conf。它允许 ZFS 缓存流式/顺序数据。仅当您的缓存设备比您的阵列更快时才这样做,就像我的一样。

在受益于我的数据集上的记录大小变化后,我认为这可能是处理不佳的 zvol 性能的类似方法。

我听到一些人说他们使用 获得了良好的性能volblocksize=64k,所以我尝试了一下。没有运气。

zfs create -b 64k -V 120G pool/volume

但后来我读到 ext4(我测试的文件系统)支持 RAID 选项,如stridestripe-width,这是我以前从未使用过的。所以我使用这个网站来计算所需的设置:https://busybox.net/~aldot/mkfs_stride.html并再次格式化 zvol。

mkfs.ext3 -b 4096 -E stride=16,stripe-width=32 /dev/zvol/pool/volume

我做bonnie++了一个简单的基准测试,结果非常好。遗憾的是,我没有拿到结果,但我记得写入速度至少快了 5-6 倍。如果我再次进行基准测试,我会再次更新此答案。

答案2

您的结果完全合理,但您的期望却不合理:您夸大了 RAID1(以及 RAID10)带来的读取性能改进。关键在于双向镜像最多单个磁盘的读取速度/IOP 是 2 倍,但实际性能可能在 1 倍到 2 倍之间。

让我们通过一个例子来说明。假设有一个具有双向镜像的系统,每个磁盘能够达到 100 MB/s(顺序)和 200 IOPS。队列深度为 1(最多一个未完成的请求),该阵列将具有优于单个磁盘:RAID1 将 IO 请求拆分到两个磁盘的队列中,但它不是将单个请求拆分到两个磁盘上(至少,我见过的任何实现都是以这种方式运行的)。另一方面,如果您的 IO 队列更大(例如:您有 4/8 个未完成的请求),则总磁盘吞吐量将明显高于单个磁盘。

对于 RAID0 也可以做类似的事情,但在这种情况下,决定平均改进的不仅是队列大小,而且IO 请求大小也:如果你的平均 IO 大小小于块大小,那么它将不是可以在两个(或更多)磁盘上进行条带化,但将由单个磁盘提供服务。使用增加的 Bonnie++ 记录大小的结果显示了这种确切的行为:条带化极大地受益于更大的 IO 大小。

现在应该清楚的是,将两个 RAID 级别组合成 RAID10 阵列将不是导致线性性能扩展,但它设置了一个上限对此。我很确定,如果您运行多个 dd/bonnie++ 实例(或用于fio直接操作 IO 队列),您将获得更符合您最初预期的结果,这仅仅是因为您将以更完整的方式(多个未完成的顺序/随机 IO 请求)对您的 IO 阵列进行征税,而不是单独加载单个顺序 IO 请求。

答案3

zfs 写入并不是很快,但也不差。zfs 读取非常慢,请自己看一下:1)#准备:cd /mytestpool/mytestzfs;for f in urf{0..9};do dd if=/dev/urandom of=$f bs=1M count=102400;done;#获取包含大量子目录和文件(~50GB)的目录路径并检查大小,例如:du -sh /mytestpool/mytestzfs/appsdir2)重启3)时间 cat /mytestpool/mytestzfs/urf0 >/dev/null;date;for f in /mytestpool/mytestzfs/urf{1..9};do cat $f >/dev/null & wait;done;date; time tar cf - /mytestpool/mytestzfs/appsdir|cat - >/dev/null 4) #查看 iostat、iotop 或 zpool iostat:您会看到太多内容! 5) 读取完成后,使用计算器除以 singlefilesize/sec,除以 9x singlefilessize/sec,再除以 directorysize/sec。这就是当磁盘上的数据越来越多,内存也越来越多时,您从 zfs 中得到的结果。

相关内容