我对 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]
4K 随机写入时 IOPS 为 57K。相当不错。
然后,我创建了一个横跨所有 8 个的 ZFS 卷。起初,我有一个raidz1
包含所有 8 个 SSD 的 vdev,但我读到了这样做对性能不利的原因,所以我最终得到了四个mirror
vdev,如下所示:
$ 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 - - - - - -
我将记录大小设置为 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]
我在这个 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
我从列出的 zfs repo 安装了 ZFS这里。我有该软件包的 0.6.5.5 版本zfs
。
更新:根据@ewwhite的建议,我尝试ashift=12
了ashift=13
:
$ sudo zpool create testpool mirror xvdb xvdc mirror xvdd xvde mirror xvdf xvdg mirror xvdh xvdi -o ashift=12 -f
和
$ sudo zpool create testpool mirror xvdb xvdc mirror xvdd xvde mirror xvdf xvdg mirror xvdh xvdi -o ashift=13 -f
这两个都没什么区别。据我所知,最新的 ZFS 已经足够智能,可以识别 4K SSD 并使用合理的默认值。
但是我确实注意到 CPU 使用率正在飙升。@Tim 建议这样做,但我拒绝了,因为我认为我观察 CPU 的时间不够长,没有注意到。此实例上有大约 30 个 CPU 核心,CPU 使用率飙升至 80%。耗电进程? z_wr_iss
,有很多这样的实例。
我确认压缩已关闭,所以它不是压缩引擎。
我没有使用 raidz,所以它不应该是奇偶校验计算。
我做了一个,它显示了在和中perf top
花费的大部分内核时间。_raw_spin_unlock_irqrestore
z_wr_int_4
osq_lock
z_wr_iss
我现在相信这个性能瓶颈有一个 CPU 组件,尽管我还没有弄清楚它到底是什么。
更新2:根据 @ewwhite 和其他人的建议,正是这种环境的虚拟化特性造成了性能不确定性,我曾经对fio
环境中四个 SSD 上的随机 4K 写入进行基准测试。每个 SSD 本身提供 ~55K IOPS,所以我预计四个 SSD 上的 IO 大约为 240K。这就是我得到的大致结果:
$ 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]
这清楚地表明,尽管环境是虚拟化的,但可以维持比我看到的更高的 IOPS。ZFS 的实现方式阻止它达到最高速度。我就是搞不清楚那是什么。
答案1
此设置可能调整得不太好。使用 SSD 时,/etc/modprobe/zfs.conf 文件和 ashift 值都需要一些参数
尝试 ashift=12 或 13,然后再次测试。
编辑:
这仍然是一个虚拟化解决方案,所以我们对底层硬件或所有东西如何互连了解不多。我不知道这个解决方案是否能带来更好的性能。
编辑:
我想我认为以这种方式优化云实例没有任何意义。因为如果目标是实现最佳性能,那么您会使用硬件,对吗?
但请记住,ZFS 有一个很多可调设置,并且您默认获得的内容与您的使用情况相差甚远。
在您的计算机上尝试以下操作/etc/modprobe.d/zfs.conf
并重新启动。这是我在全 SSD 数据池中为应用服务器使用的。您的 ashift 应该是 12 或 13。使用 compression=off 进行基准测试,但在生产中使用 compression=lz4。设置 atime=off。我会将 recordsize 保留为默认值 (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
答案2
看起来你正在等待 Linux 内核互斥锁,而这个互斥锁又可能在等待 Xen 环形缓冲区。如果没有类似的机器,我无法确定这一点,但我不想为这个特权向亚马逊支付每小时 7 美元。
更长的写作内容在这里:https://www.reddit.com/r/zfs/comments/4b4r1y/why_is_zfs_on_linux_unable_to_fully_utilize_8x/d1e91wo;我宁愿它在一个地方,而不是两个地方。
答案3
我花了相当多的时间来尝试解决这个问题。我的具体挑战是:一台 Postgres 服务器,我想使用 ZFS 来存储其数据量。基准是 XFS。
首先,我的试验告诉我这ashift=12
是错的。如果有一个神奇的ashift
数字,它不是 12。我正在使用0
,并且得到了非常好的结果。
我还尝试了许多 zfs 选项,其中给出以下结果的选项是:
atime=off
- 我不需要访问时间
checksum=off
- 我是条纹,不是镜像
compression=lz4
- 表现更好具有压缩功能(CPU 权衡?)
exec=off
- 这是针对数据,不是可执行文件
logbias=throughput
- 在互联网上读到这对 Postgres 更好
recordsize=8k
- PG 特定的 8k 块大小
sync=standard
- 尝试关闭同步;没有看到太多好处
我的以下测试显示出比 XFS 性能更好(如果您发现我的测试中有错误,请发表评论!)。
我的下一步是尝试在 2 x EBS ZFS 文件系统上运行 Postgres。
我的具体设置:
EC2:m4.xlarge
实例
EBS:250GBgp2
卷
内核:Linux [...] 3.13.0-105-通用#152-Ubuntu SMP [...] x86_64 x86_64 x86_64 GNU/Linux *
首先,我想测试原始 EBS 性能。使用fio
上述命令的变体,我得出了下面的咒语。注意:我使用 8k 块,因为我读到 PostgreSQL 写入的内容如下:
ubuntu@ip-172-31-30-233:~$ device=/dev/xvdbd; sudo dd if=/dev/zero of=${device} bs=1M count=100 && sudo fio --name randwrite --ioengine=libaio --iodepth=4 --rw=randwrite --bs=8k --size=400G --numjobs=4 --runtime=60 --group_reporting --fallocate=none --filename=${device}
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 0.250631 s, 418 MB/s
randwrite: (g=0): rw=randwrite, bs=8K-8K/8K-8K/8K-8K, ioengine=libaio, iodepth=4
...
randwrite: (g=0): rw=randwrite, bs=8K-8K/8K-8K/8K-8K, ioengine=libaio, iodepth=4
fio-2.1.3
Starting 4 processes
Jobs: 4 (f=4): [wwww] [100.0% done] [0KB/13552KB/0KB /s] [0/1694/0 iops] [eta 00m:00s]
randwrite: (groupid=0, jobs=4): err= 0: pid=18109: Tue Feb 14 19:13:53 2017
write: io=3192.2MB, bw=54184KB/s, iops=6773, runt= 60327msec
slat (usec): min=2, max=805209, avg=585.73, stdev=6238.19
clat (usec): min=4, max=805236, avg=1763.29, stdev=10716.41
lat (usec): min=15, max=805241, avg=2349.30, stdev=12321.43
clat percentiles (usec):
| 1.00th=[ 15], 5.00th=[ 16], 10.00th=[ 17], 20.00th=[ 19],
| 30.00th=[ 23], 40.00th=[ 24], 50.00th=[ 25], 60.00th=[ 26],
| 70.00th=[ 27], 80.00th=[ 29], 90.00th=[ 36], 95.00th=[15808],
| 99.00th=[31872], 99.50th=[35584], 99.90th=[99840], 99.95th=[199680],
| 99.99th=[399360]
bw (KB /s): min= 156, max=1025440, per=26.00%, avg=14088.05, stdev=67584.25
lat (usec) : 10=0.01%, 20=20.53%, 50=72.20%, 100=0.86%, 250=0.17%
lat (usec) : 500=0.13%, 750=0.01%, 1000=0.01%
lat (msec) : 2=0.01%, 4=0.01%, 10=0.59%, 20=2.01%, 50=3.29%
lat (msec) : 100=0.11%, 250=0.05%, 500=0.02%, 750=0.01%, 1000=0.01%
cpu : usr=0.22%, sys=1.34%, ctx=9832, majf=0, minf=114
IO depths : 1=0.1%, 2=0.1%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
issued : total=r=0/w=408595/d=0, short=r=0/w=0/d=0
Run status group 0 (all jobs):
WRITE: io=3192.2MB, aggrb=54184KB/s, minb=54184KB/s, maxb=54184KB/s, mint=60327msec, maxt=60327msec
Disk stats (read/write):
xvdbd: ios=170/187241, merge=0/190688, ticks=180/8586692, in_queue=8590296, util=99.51%
EBS 卷的原始性能为WRITE: io=3192.2MB
。
现在,使用相同的fio
命令测试 XFS:
Jobs: 4 (f=4): [wwww] [100.0% done] [0KB/0KB/0KB /s] [0/0/0 iops] [eta 00m:00s]
randwrite: (groupid=0, jobs=4): err= 0: pid=17441: Tue Feb 14 19:10:27 2017
write: io=3181.9MB, bw=54282KB/s, iops=6785, runt= 60024msec
slat (usec): min=3, max=21077K, avg=587.19, stdev=76081.88
clat (usec): min=4, max=21077K, avg=1768.72, stdev=131857.04
lat (usec): min=23, max=21077K, avg=2356.23, stdev=152444.62
clat percentiles (usec):
| 1.00th=[ 29], 5.00th=[ 40], 10.00th=[ 46], 20.00th=[ 52],
| 30.00th=[ 56], 40.00th=[ 59], 50.00th=[ 63], 60.00th=[ 69],
| 70.00th=[ 79], 80.00th=[ 99], 90.00th=[ 137], 95.00th=[ 274],
| 99.00th=[17024], 99.50th=[25472], 99.90th=[70144], 99.95th=[120320],
| 99.99th=[1564672]
bw (KB /s): min= 2, max=239872, per=66.72%, avg=36217.04, stdev=51480.84
lat (usec) : 10=0.01%, 20=0.03%, 50=15.58%, 100=64.51%, 250=14.55%
lat (usec) : 500=1.36%, 750=0.33%, 1000=0.25%
lat (msec) : 2=0.68%, 4=0.67%, 10=0.71%, 20=0.58%, 50=0.59%
lat (msec) : 100=0.10%, 250=0.02%, 500=0.01%, 750=0.01%, 1000=0.01%
lat (msec) : 2000=0.01%, >=2000=0.01%
cpu : usr=0.43%, sys=4.81%, ctx=269518, majf=0, minf=110
IO depths : 1=0.1%, 2=0.1%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
issued : total=r=0/w=407278/d=0, short=r=0/w=0/d=0
Run status group 0 (all jobs):
WRITE: io=3181.9MB, aggrb=54282KB/s, minb=54282KB/s, maxb=54282KB/s, mint=60024msec, maxt=60024msec
Disk stats (read/write):
xvdbd: ios=4/50983, merge=0/319694, ticks=0/2067760, in_queue=2069888, util=26.21%
我们的基线WRITE: io=3181.9MB
非常接近原始磁盘速度。
现在,以 ZFSWRITE: io=3181.9MB
为参考:
ubuntu@ip-172-31-30-233:~$ sudo zpool create testpool xvdbd -f && (for option in atime=off checksum=off compression=lz4 exec=off logbias=throughput recordsize=8k sync=standard; do sudo zfs set $option testpool; done;) && sudo fio --name randwrite --ioengine=libaio --iodepth=4 --rw=randwrite --bs=8k --size=400G --numjobs=4 --runtime=60 --group_reporting --fallocate=none --filename=/testpool/testfile; sudo zpool destroy testpool
randwrite: (g=0): rw=randwrite, bs=8K-8K/8K-8K/8K-8K, ioengine=libaio, iodepth=4
...
randwrite: (g=0): rw=randwrite, bs=8K-8K/8K-8K/8K-8K, ioengine=libaio, iodepth=4
fio-2.1.3
Starting 4 processes
randwrite: Laying out IO file(s) (1 file(s) / 409600MB)
randwrite: Laying out IO file(s) (1 file(s) / 409600MB)
randwrite: Laying out IO file(s) (1 file(s) / 409600MB)
randwrite: Laying out IO file(s) (1 file(s) / 409600MB)
Jobs: 4 (f=4): [wwww] [100.0% done] [0KB/41328KB/0KB /s] [0/5166/0 iops] [eta 00m:00s]
randwrite: (groupid=0, jobs=4): err= 0: pid=18923: Tue Feb 14 19:17:18 2017
write: io=4191.7MB, bw=71536KB/s, iops=8941, runt= 60001msec
slat (usec): min=10, max=1399.9K, avg=442.26, stdev=4482.85
clat (usec): min=2, max=1400.4K, avg=1343.38, stdev=7805.37
lat (usec): min=56, max=1400.4K, avg=1786.61, stdev=9044.27
clat percentiles (usec):
| 1.00th=[ 62], 5.00th=[ 75], 10.00th=[ 87], 20.00th=[ 108],
| 30.00th=[ 122], 40.00th=[ 167], 50.00th=[ 620], 60.00th=[ 1176],
| 70.00th=[ 1496], 80.00th=[ 2320], 90.00th=[ 2992], 95.00th=[ 4128],
| 99.00th=[ 6816], 99.50th=[ 9536], 99.90th=[30592], 99.95th=[66048],
| 99.99th=[185344]
bw (KB /s): min= 2332, max=82848, per=25.46%, avg=18211.64, stdev=15010.61
lat (usec) : 4=0.01%, 50=0.09%, 100=14.60%, 250=26.77%, 500=5.96%
lat (usec) : 750=5.27%, 1000=4.24%
lat (msec) : 2=20.96%, 4=16.74%, 10=4.93%, 20=0.30%, 50=0.08%
lat (msec) : 100=0.04%, 250=0.03%, 500=0.01%, 2000=0.01%
cpu : usr=0.61%, sys=9.48%, ctx=177901, majf=0, minf=107
IO depths : 1=0.1%, 2=0.1%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
issued : total=r=0/w=536527/d=0, short=r=0/w=0/d=0
Run status group 0 (all jobs):
WRITE: io=4191.7MB, aggrb=71535KB/s, minb=71535KB/s, maxb=71535KB/s, mint=60001msec, maxt=60001msec
注意,它的表现比 XFS 更好WRITE: io=4191.7MB
。我确信这是由于压缩。
为了好玩,我将添加第二卷:
ubuntu@ip-172-31-30-233:~$ sudo zpool create testpool xvdb{c,d} -f && (for option in atime=off checksum=off compression=lz4 exec=off logbias=throughput recordsize=8k sync=standard; do sudo zfs set $option testpool; done;) && sudo fio --name randwrite --ioengine=libaio --iodepth=4 --rw=randwrite --bs=8k --size=400G --numjobs=4 --runtime=60 --group_reporting --fallocate=none --filename=/testpool/testfile; sudo zpool destroy testpool
randwrite: (g=0): rw=randwrite, bs=8K-8K/8K-8K/8K-8K, ioengine=libaio, iodepth=4
...
randwrite: (g=0): rw=randwrite, bs=8K-8K/8K-8K/8K-8K, ioengine=libaio, iodepth=4
fio-2.1.3
Starting 4 processes
randwrite: Laying out IO file(s) (1 file(s) / 409600MB)
randwrite: Laying out IO file(s) (1 file(s) / 409600MB)
randwrite: Laying out IO file(s) (1 file(s) / 409600MB)
randwrite: Laying out IO file(s) (1 file(s) / 409600MB)
Jobs: 4 (f=4): [wwww] [100.0% done] [0KB/71936KB/0KB /s] [0/8992/0 iops] [eta 00m:00s]
randwrite: (groupid=0, jobs=4): err= 0: pid=20901: Tue Feb 14 19:23:30 2017
write: io=5975.9MB, bw=101983KB/s, iops=12747, runt= 60003msec
slat (usec): min=10, max=1831.2K, avg=308.61, stdev=4419.95
clat (usec): min=3, max=1831.6K, avg=942.64, stdev=7696.18
lat (usec): min=58, max=1831.8K, avg=1252.25, stdev=8896.67
clat percentiles (usec):
| 1.00th=[ 70], 5.00th=[ 92], 10.00th=[ 106], 20.00th=[ 129],
| 30.00th=[ 386], 40.00th=[ 490], 50.00th=[ 692], 60.00th=[ 796],
| 70.00th=[ 932], 80.00th=[ 1160], 90.00th=[ 1624], 95.00th=[ 2256],
| 99.00th=[ 5344], 99.50th=[ 8512], 99.90th=[30592], 99.95th=[60672],
| 99.99th=[117248]
bw (KB /s): min= 52, max=112576, per=25.61%, avg=26116.98, stdev=15313.32
lat (usec) : 4=0.01%, 10=0.01%, 50=0.04%, 100=7.17%, 250=19.04%
lat (usec) : 500=14.36%, 750=15.36%, 1000=17.41%
lat (msec) : 2=20.28%, 4=4.82%, 10=1.13%, 20=0.25%, 50=0.08%
lat (msec) : 100=0.04%, 250=0.02%, 2000=0.01%
cpu : usr=1.05%, sys=15.14%, ctx=396649, majf=0, minf=103
IO depths : 1=0.1%, 2=0.1%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
issued : total=r=0/w=764909/d=0, short=r=0/w=0/d=0
Run status group 0 (all jobs):
WRITE: io=5975.9MB, aggrb=101982KB/s, minb=101982KB/s, maxb=101982KB/s, mint=60003msec, maxt=60003msec
有了第二卷,WRITE: io=5975.9MB
写入量就增加了约 1.8 倍。
第三卷给了我们WRITE: io=6667.5MB
,所以写入量是~2.1X。
第四个卷给了我们WRITE: io=6552.9MB
。对于这种实例类型,看起来我用两个卷几乎就限制了 EBS 网络,绝对用三个,用 4 个也好不到哪里去(750 * 3 = 2250 IOPS)。
* 从这个视频确保您正在使用 3.8+ Linux 内核来获取所有 EBS 优点。