0x01 前言
最近我的服务器在测试中发现有许多IO警告,分析日志发现虚拟机的IO都很低,磁盘写入速度只有5m/s到20m/s。在审查配置后发现没有修改默认的缓存模式。
0x02 模式
在centos7中,有以下五种缓存模式:
- none:虚拟机的IO不会被服务器缓存,但有可能被物理磁盘或阵列控制器缓存
- writethrough:虚拟机的IO缓存在服务器,而且数据立即刷新到物理磁盘中
- writeback:虚拟机的IO缓存在服务器
- directsync:和writethrough类似,但虚拟机的IO会绕过服务器的页面文件
- unsafe:服务器会缓存所以来自虚拟机的IO,同时忽略来自虚拟机的disk sync请求
- default:如果不手动指定缓存模式,那么将会使用默认的缓存模式
在配置虚拟机时如果不指定缓存模式,那么writethrough将作为默认的缓存模式。不同的qemu-kvm可能会有不同的默认缓存模式,想查询kvm服务器中默认的缓存模式,可以使用以下方式:
#输入以下命令 [root@server ~]# qemu-img -h #在返还的内容中找到以下内容 'cache' is the cache mode used to write the output disk image, the valid options are: 'none', 'writeback' (default, except for convert), 'writethrough', 'directsync' and 'unsafe' (default for convert)
我的服务器以writeback作为默认的缓存模式。如果服务器的raid缓存没有电池供电,那么默认的缓存模式很有可能为writethrough。
0x03 安全
数据安全是第一位,如果选用缓存模式不慎,极有可能会导致数据丢失。下图为缓存模式IO示意图:
none与writethrough比writeback有较高的安全性。
根据上图,writeback模式下,来自虚拟机的IO会被写入服务器的页面文件中。不建议在raid缓存没有电池的情况下使用writeback模式,服务器一旦断电,还在缓存中的数据将会丢失。
writethrough的安全性最高,因为是直接写入到物理磁盘中,但同时也会损失掉一部分性能。
0x04 性能
下面我用同一个虚拟机分别测试以上五种缓存模式,测试所使用的物理磁盘的最高速度为330m/s,由4块2TB硬盘组成raid10,阵列卡有512M缓存并带有电池。以下是虚拟磁盘的信息:
[root@server ~]# qemu-img info /disk2/kvm/images/test_images/io_test_1.img image: /disk2/kvm/images/test_images/io_test_1.img file format: qcow2 virtual size: 20G (21474836480 bytes) disk size: 2.0G cluster_size: 65536 Format specific information: compat: 1.1 lazy refcounts: true
使用以下命令进行测试:
dd bs=1M count=1024 if=/dev/zero of=1gb.test conv=fdatasync
每一个模式将测试5次,以下是缓存模式为none的结果:
[root@io-test-1 disk2]# dd bs=1M count=1024 if=/dev/zero of=1gb.test conv=fdatasync 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB) copied, 6.8543 s, 157 MB/s [root@io-test-1 disk2]# dd bs=1M count=1024 if=/dev/zero of=1gb.test conv=fdatasync 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB) copied, 5.83386 s, 184 MB/s [root@io-test-1 disk2]# dd bs=1M count=1024 if=/dev/zero of=1gb.test conv=fdatasync 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB) copied, 5.40407 s, 199 MB/s [root@io-test-1 disk2]# dd bs=1M count=1024 if=/dev/zero of=1gb.test conv=fdatasync 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB) copied, 5.25176 s, 204 MB/s [root@io-test-1 disk2]# dd bs=1M count=1024 if=/dev/zero of=1gb.test conv=fdatasync 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB) copied, 4.94201 s, 217 MB/s
以下是缓存模式为writethrough的测试结果:
[root@io-test-1 disk2]# dd bs=1M count=1024 if=/dev/zero of=1gb.test conv=fdatasync 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB) copied, 7.44214 s, 144 MB/s [root@io-test-1 disk2]# dd bs=1M count=1024 if=/dev/zero of=1gb.test conv=fdatasync 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB) copied, 5.90264 s, 182 MB/s [root@io-test-1 disk2]# dd bs=1M count=1024 if=/dev/zero of=1gb.test conv=fdatasync 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB) copied, 5.85222 s, 183 MB/s [root@io-test-1 disk2]# dd bs=1M count=1024 if=/dev/zero of=1gb.test conv=fdatasync 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB) copied, 4.9245 s, 218 MB/s [root@io-test-1 disk2]# dd bs=1M count=1024 if=/dev/zero of=1gb.test conv=fdatasync 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB) copied, 5.6933 s, 189 MB/s
以下是缓存模式为writeback的测试结果:
[root@io-test-1 disk2]# dd bs=1M count=1024 if=/dev/zero of=1gb.test conv=fdatasync 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB) copied, 6.30278 s, 170 MB/s [root@io-test-1 disk2]# dd bs=1M count=1024 if=/dev/zero of=1gb.test conv=fdatasync 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB) copied, 6.19481 s, 173 MB/s [root@io-test-1 disk2]# dd bs=1M count=1024 if=/dev/zero of=1gb.test conv=fdatasync 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB) copied, 6.06488 s, 177 MB/s [root@io-test-1 disk2]# dd bs=1M count=1024 if=/dev/zero of=1gb.test conv=fdatasync 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB) copied, 6.38592 s, 168 MB/s [root@io-test-1 disk2]# dd bs=1M count=1024 if=/dev/zero of=1gb.test conv=fdatasync 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB) copied, 6.20265 s, 173 MB/s [root@io-test-1 disk2]# dd bs=1M count=1024 if=/dev/zero of=1gb.test conv=fdatasync 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB) copied, 5.61563 s, 191 MB/s
以下是缓存模式为directsync的测试结果:
[root@io-test-1 disk2]# dd bs=1M count=1024 if=/dev/zero of=1gb.test conv=fdatasync 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB) copied, 5.10843 s, 210 MB/s [root@io-test-1 disk2]# dd bs=1M count=1024 if=/dev/zero of=1gb.test conv=fdatasync 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB) copied, 5.92729 s, 181 MB/s [root@io-test-1 disk2]# dd bs=1M count=1024 if=/dev/zero of=1gb.test conv=fdatasync 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB) copied, 5.67731 s, 189 MB/s [root@io-test-1 disk2]# dd bs=1M count=1024 if=/dev/zero of=1gb.test conv=fdatasync 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB) copied, 5.69663 s, 188 MB/s [root@io-test-1 disk2]# dd bs=1M count=1024 if=/dev/zero of=1gb.test conv=fdatasync 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB) copied, 5.46388 s, 197 MB/s
以下是缓存模式为unsafe的测试结果,以为数据并没有真实写入硬盘,所以速度非常惊人:
[root@io-test-1 disk2]# dd bs=1M count=1024 if=/dev/zero of=1gb.test conv=fdatasync 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB) copied, 1.16476 s, 922 MB/s [root@io-test-1 disk2]# dd bs=1M count=1024 if=/dev/zero of=1gb.test conv=fdatasync 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB) copied, 0.96282 s, 1.1 GB/s [root@io-test-1 disk2]# dd bs=1M count=1024 if=/dev/zero of=1gb.test conv=fdatasync 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB) copied, 0.915939 s, 1.2 GB/s [root@io-test-1 disk2]# dd bs=1M count=1024 if=/dev/zero of=1gb.test conv=fdatasync 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB) copied, 0.814352 s, 1.3 GB/s [root@io-test-1 disk2]# dd bs=1M count=1024 if=/dev/zero of=1gb.test conv=fdatasync 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB) copied, 0.897145 s, 1.2 GB/s
以下是五个缓存模式速度测试结果图标:
按预想,应该是writeback的性能略高于除了unsafe的其他模式,但我服务器上结果却是none的性能比较好。这一结果也有其他因素影响,例如我服务器正在运行的其他虚拟机和虚拟磁盘的其他参数。
0x05 配置
在使用virt-install安装虚拟机时,可以通过以下参数为虚拟磁盘指定缓存模式:
cache=writethrough
例如:
--disk path=/disk2/kvm/images/test_images/io_test_1.img,size=20,bus=virtio,cache=writethrough
如果已经安装好虚拟机,想修改缓存模式,则需要修改配置文件:
#打开配置文件 [root@server ~]# virsh edit io_test_1 #修改以下内容 <driver name='qemu' type='qcow2' cache='writeback'/>
然后重新启动虚拟机即可。
0x06 结语
数据的完整性肯定要比性能更重要,请慎重选择缓存模式。在这里推荐使用none、directsync和writethrough。