ZFS 写时复制

ZFS 写时复制

我计划使用 ZFS 进行备份。5-10 台服务器将通过 DRBD 将更新“流式传输”到 ZFS 文件系统上的非常大的文件(每个 500 GB)。

服务器每秒将产生约 20 兆字节的随机写入,总计约 100 MBps。我没有读取这些文件,因此模式应该是几乎 100% 的写入。

对我来说,写时复制是一项非常重要的功能。

据我所知,COW 应该将随机写入转换为顺序写入。但这并没有发生。

我在具有 12 个 SAS 驱动器 E5520 XEON(4 核)和 24 GB RAM 的服务器上进行了测试,随机写入非常低。

我决定先在同一台服务器上的 1 个 SAS HDD 上进行调试。

我创建了 EXT4 文件系统并做了一些测试:

 
root@zfs:/mnt/hdd/test# dd if=/dev/zero of=tempfile bs=1M count=4096 conv=f​​datasync,notrunc
4096+0 条记录
4096+0 条记录
已复制 4294967296 字节(4.3 GB),耗时 30.2524 秒,142 MB/s

所以我可以看到写入速度大约是 140 MBps。

随机写入速度约为 500 KBps 和 100-150 iops。这很正常。

fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --name=test --filename=test --bs=4k --iodepth=1 --size=4G --readwrite=randwrite
测试:(g=0):rw=randwrite,bs=4K-4K/4K-4K/4K-4K,ioengine=libaio,iodepth=1
fio-2.1.11
启动 1 个进程
bs: 1 (f=1): [w(1)] [0.6% 完成] [0KB/548KB/0KB /s] [0/137/0 iops] [eta 02h:02m:57s]

然后在同一驱动器上我创建了 ZFS:

zpool 创建 -f -m /mnt/data bigdata scsi-35000cca01b370274

我将记录大小设置为 4K,因为我将进行 4K 随机写入。我在测试时发现,记录大小 4K 比 128k 效果更好。

zfs 设置 recordsize=4k 大数据

测试了对4G文件的随机写入。

fio --randrepeat=1 --ioengine=libaio --gtod_reduce=1 --name=./test --filename=test --bs=4k --iodepth=1 --size=4G --readwrite=randwrite
./测试:(g=0):rw=randwrite,bs=4K-4K/4K-4K/4K-4K,ioengine=libaio,iodepth=1
fio-2.1.11
启动 1 个进程
./test: 布局 IO 文件 (1 个文件 / 4096MB)
作业:1(f=1):[w(1)] [100.0% 完成] [0KB/115.9MB/0KB /s] [0/29.7K/0 iops] [
[预计到达时间 00 分:00 秒]

看起来 COW 在这里表现不错,每秒 115.9MB。

测试了对16G文件的随机写入。

fio --randrepeat=1 --ioengine=libaio --gtod_reduce=1 --name=test --filename=./test16G --bs=4k --iodepth=1 --size=16G --readwrite=randwrite

测试:(g=0):rw=randwrite,bs=4K-4K/4K-4K/4K-4K,ioengine=libaio,iodepth=1
fio-2.1.11
启动 1 个进程
bs: 1 (f=1): [w(1)] [0.1% 完成] [0KB/404KB/0KB /s] [0/101/0 iops] [eta 02h:08m:55s]

每秒 400 千字节的结果非常糟糕。

对 8G 文件进行了相同的尝试:

fio --randrepeat=1 --ioengine=libaio --gtod_reduce=1 --name=test --filename=./test8G --bs=4k --iodepth=1 --size=8G --readwrite=randwrite

测试:(g=0):rw=randwrite,bs=4K-4K/4K-4K/4K-4K,ioengine=libaio,iodepth=1
fio-2.1.11
启动 1 个进程
测试:布局 IO 文件 (1 个文件 / 8192MB)

bs:1(f=1):[w(1)] [14.5% 完成] [0KB/158.3MB/0KB /s] [0/40.6K/0 iops] [eta 00m:53s]

一开始,COW 的速度是每秒 136 兆字节。

设备:rrqm/s wrqm/sr/sw/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sda 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
可持续发展目标 0.00 0.00 0.00 1120.00 0.00 136.65 249.88 9.53 8.51 0.00 8.51 0.89 99.24

但最后当测试达到 90% 时,写入速度下降到每秒 5 兆字节。

设备:rrqm/s wrqm/sr/sw/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sda 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
可持续发展目标 0.00 0.00 0.00 805.90 0.00 5.33 13.54 9.95 12.34 0.00 12.34 1.24 100.00

因此 4G 文件没有问题,8G 也差不多没问题,但是 16G 文件不会出现任何 COW。

不明白这里发生了什么。也许内存缓存在这里起了作用。

操作系统:Debian 8 ZFS ver 500。无压缩或重复数据删除。

zpool 列表
名称 大小 分配 空闲 EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
大数据 1.81T 64.4G 1.75T - 2% 3% 1.00x 在线 -


root@zfs:/mnt/data/test# zdb
大数据:
    版本:5000
    名称:'大数据'
    状态:0
    交易量:4
    pool_guid:16909063556944448541
    勘误表:0
    主机 ID:8323329
    主机名:'zfs'
    vdev_children: 1
    vdev_tree:
        类型:'root'
        id:0
        指导编号:16909063556944448541
        创建交易:4
        孩子[0]:
            类型:'磁盘'
            id:0
            指导编号:8547466691663463210
            路径:'/dev/disk/by-id/scsi-35000cca01b370274-part1'
            整个磁盘: 1
            metaslab_array: 34
            metaslab_shift: 34
            移位:9
            大小: 2000384688128
            是日志: 0
            创建交易:4
    可供阅读的功能:
        com.delphix:hole_birth
        com.delphix:embedded_data



zpool 状态大数据
  池:bigdata
 状态: 在线
  扫描:未请求
配置:

    名称 状态 读写 CKSUM
    大数据在线 0 0 0
      scsi-35000cca01b370274 在线 0 0 0
错误:没有已知数据错误

fio 无法与 ZFS 上的 O_DIRECT 配合使用,因此我不得不在没有它的情况下运行。据我所知,它应该能产生更好的结果。但事实并非如此。

fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --name=./test --filename=test16G --bs=4k --iodepth=1 --size=16G --readwrite=randwrite
./测试:(g=0):rw=randwrite,bs=4K-4K/4K-4K/4K-4K,ioengine=libaio,iodepth=1
fio-2.1.11
启动 1 个进程
fio:看起来你的文件系统不支持 direct=1/buffered=0
fio:目标不支持 O_DIRECT

答案1

这不是一场公平的战斗:

  • 当你使用ddfio默认生成单个随机块并在可能时重复使用它。由于所有零都(稍微)更可压缩,因此这可能会扭曲数字。
  • 您使用的块大小为 1MByte,而您的线路dd使用的大小为 4KBytes。fio
  • 您将运行次数限制iodepthfio仅 1(此选择与上面的小于 dd 块大小的选择相结合)。
  • dd始终可以使用写回缓存,但其中一次fio运行却不被允许(因为您设置了direct=1)!
  • 因为你的 ZFS 版本不“允许”,O_DIRECT即使你尝试使用更高的深度,libaio提交也不会异步(请参阅Linux 上的 SSD IOPS,DIRECT 比缓冲、fio 快得多),但由于最大未完成 I/O 限制为一个(参见上文),因此这是一个没有实际意义的问题。
  • 相对于内存大小(24GB),您dd写入的数据非常少(4GB),以至于 Linux 在完成时可能在其页面缓存中仍会保留大量写入数据。您必须至少执行某种文件同步,以确保它确实到达了非易失性存储...评论中指出 conv=fdatasync已设置dd,因此在退出之前将会有一个最后的 fdatasync,以确保数据不仅存在于非易失性缓存中。
  • 您正在将 Ext4 卷上的顺序与 ZFS 卷上的随机进行比较(您在比较之间更改了工作负载和文件系统)。

在最低限度上,我建议重新开始,在 ZFS 上进行所有测试,用于fio顺序和随机测试,其余部分保持不变。我还会考虑使用类似end_fsync以确保数据确实到达磁盘,而不仅仅是存在于非易失性缓存中(但我可以看到跳过这一部分的论点)。

TLDR;我担心您的比较方法有缺陷——也许在比较之间减少改变会更好?

相关内容