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

我对ZFS完全陌生,所以首先我想我会做一些简单的基准testing来了解它的行为。 我想要突破它的性能限制,所以我configuration了一个Amazon EC2 i2.8xlarge实例(几乎是7美元/小时,时间真的就是金钱!)。 这个实例有8个800GB SSD。

我对SSD自己做了一个fiotesting,并得到了以下输出(修剪):

 $ 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] 

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

然后我创build了一个跨越全部8个ZFS卷。起初我有一个raidz1 vdev与所有8固态硬盘在里面,但我读了性能不好的原因,所以我最终有四个mirror vdevs,如下所示:

 $ 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 - - - - - - 

我将logging大小设置为4K,然后运行我的testing:

 $ 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本身稍微差一些。

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

注意我正在使用官方的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回购安装了ZFS。 我有zfs软件包的0.6.5.5版本。

更新 :Per @ ewwhite的build议我试过了ashift=12ashift=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提出了这个build议,但是我否认了这一点,但是我认为我没有注意到CPU太长了。 在这个例子中有30个CPU核心,CPU使用率高达80%。 饥饿的过程? z_wr_iss ,它的很多实例。

我确认压缩closures,所以它不是压缩引擎。

我不使用raidz,所以它不应该是平价计算。

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

我现在认为这个性能瓶颈有一个CPU组件,尽pipe我并没有仔细考虑它是什么。

更新2 :Per @ ewwhite和其他人的build议是,这种环境的虚拟化特性造成了性能的不确定性,我使用fio来testing在环境中的四个SSD上散布的随机4K写入。 每个固态硬盘本身的IOPS达到了约55K,所以我预计其中四个固态硬盘将会有大约240K的IO。 这或多或less是我得到的:

 $ 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的实施方式,使它不能达到最高速度。 我只是无法弄清楚是什么。

这个设置可能不太适合。 使用SSD时,/etc/modprobe/zfs.conf文件和ashift值都需要参数

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


编辑:

这仍然是一个虚拟化的解决scheme,所以我们不太了解底层硬件或者一切是如何相互连接的。 我不知道你会从这个解决scheme中获得更好的性能。


编辑:

我想我没有看到试图以这种方式优化云实例。 因为如果顶级的performance是目标,你会使用硬件,对吧?

但请记住,ZFS有很多可调整的设置,默认情况下不会接近您的用例。

/etc/modprobe.d/zfs.conf尝试以下内容并重新启动。 这就是我在应用程序服务器的全SSD数据池中使用的内容。 你的ashift应该是12或13.基准压缩= off,但在生产中使用compression = lz4。 设置时间=closures。 我会把logging保留为默认值(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 

看起来您可能正在等待Linux内核互斥锁,而后者又可能正在等待Xen环形缓冲区。 如果不能访问类似的机器,我无法确定这一点,但我并不感兴趣支付亚马逊每小时7美元的特权。

更长的时间写在这里: https : //www.reddit.com/r/zfs/comments/4b4r1y/why_is_zfs_on_linux_unable_to_fully_utilize_8x/d1e91wo ; 我宁愿它在一个地方比两个。

我已经花了相当多的时间试图追查下来。 我的具体挑战:一个Postgres服务器,我想使用ZFS的数据量。 基准是XFS。

首先,我的试验告诉我, ashift=12是错误的。 如果有一些神奇的ashift数,它不是12.我使用0 ,我得到了非常好的结果。

我也尝试了一堆zfs选项,那些给我以下结果的是:

atime=off – 我不需要访问时间

checksum=off – 我是条纹,而不是镜像

compression=lz4compression=lz4性能更好 (cpu折衷?)

exec=off – 这是为了数据,而不是可执行文件

logbias=throughput – 阅读interwebs这是更好的Postgres

recordsize=8k – PG特定的8k块大小

sync=standard – 试图closures同步; 没有看到太多的好处

我的testing显示比XFS更好(如果您在我的testing中看到错误,请发表评论!)。

有了这个,我的下一步就是尝试运行在2个EBS ZFS文件系统上的Postgres。

我的具体设置:

EC2: m4.xlarge实例

EBS:250GB gp2

内核:Linux […] 3.13.0-105-generic#152 -Ubuntu SMP x86_64 x86_64 x86_64 GNU / Linux *

首先,我想testingEBS的原始性能。 使用上面的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命令testingXFS:

 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 ; 真的接近原始磁盘速度。

现在,用WRITE: 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执行得更好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 。 对于这个实例types,看起来我几乎用两个卷来限制EBSnetworking,绝对是三个,对于4(750 * 3 = 2250 IOPS),情况并不是这样。

*从这个video确保你使用3.8+的Linux内核获得所有的EBS善良。