17 磁盘缓存模式 #
17.1 磁盘接口缓存模式 #
超级管理程序允许在配置 VM Guest 时指定各种储存缓存策略。可为每个 Guest 磁盘接口指定以下缓存模式之一:writethrough、writeback、none、directsync 或 unsafe。如果未指定任何模式,将使用相应的默认缓存模式。这些缓存模式会影响基于主机的储存的访问方式,如下所述:
读取/写入数据可以缓存在主机页缓存中。
Guest 的储存控制器会获悉是否存在写入缓存,以便能够使用刷新命令。
可以使用同步写入模式,在此模式下,仅当已将写入请求提交到储存设备时,才将这些请求报告为完成。
可出于性能原因忽略刷新命令(由 Guest 储存控制器生成)。
如果 Guest 与其储存设备之间的连接无序断开,则使用的缓存模式将影响到是否会发生数据丢失。缓存模式还会显著影响磁盘性能。此外,某些缓存模式与实时迁移不兼容,具体取决于多个因素。有关缓存模式、磁盘映像格式、映像位置和储存子系统的哪种组合是最佳的,并没有简单的规则可循。用户应该精心规划每个 Guest 的配置,并试验各种配置来确定最佳性能。
17.2 缓存模式的说明 #
- 未指定缓存模式
在较早的 QEMU 版本中,不指定缓存模式意味着使用 writethrough 作为默认模式。在 SUSE Linux Enterprise Server 随附的新版本中,已将各种 Guest 储存接口固定下来,可以更正确地处理 writeback 或 writethrough 语义。这样就可以将默认缓存模式切换到 writeback。
ide
、scsi
和virtio
的 Guest 驱动程序必须各尽所能地禁用写回缓存,以使所用的缓存模式还原为 writethrough。不过,典型的 Guest 储存驱动程序会将默认缓存模式保留为 writeback。- writethrough(直写)
此模式会导致超级管理程序使用
O_DSYNC
语义来与磁盘映像文件或块设备交互。仅当已将数据提交到储存设备后,才将写入操作报告为已完成。以称为直写的缓存模式来使用主机页缓存。Guest 的虚拟储存适配器将获悉不存在写回缓存,因此 Guest 无需发送刷新命令来管理数据完整性。储存设备会像存在直写缓存一样工作。- writeback(写回)
此模式会导致超级管理程序既不使用
O_DSYNC
,也不使用O_DIRECT
语义来与磁盘映像文件或块设备交互。将使用主机页缓存,在将写入内容放入主机页缓存后,即会向 Guest 报告写入操作已完成。常规页缓存管理仍会处理向储存设备提交内容的操作。此外,会向 Guest 的虚拟储存适配器告知写回缓存,因此 Guest 预期会按需发送刷新命令来管理数据完整性。类似于具有 RAM 缓存的 raid 控制器。- none(无)
此模式会导致超级管理程序使用
O_DIRECT
语义来与磁盘映像文件或块设备交互。将绕过主机页缓存,I/O 直接在超级管理程序用户空间缓冲区与储存设备之间发生。由于仅当已将写入内容放入其写入队列后,实际储存设备才能将写入操作报告为已完成,因此 Guest 的虚拟储存适配器将获悉存在写回缓存这一情况。Guest 预期会按需发送刷新命令来管理数据完整性。以性能为导向,相当于直接访问主机的磁盘。- unsafe(不安全)
此模式与前面所述的
writeback
模式类似。此“unsafe”模式的主要特定是,将忽略来自 Guest 的所有刷新命令。使用此模式意味着用户同意性能优先,可以接受主机发生故障时数据可能丢失的风险。在安装 Guest 等情形下很有用,但对于生产工作负载并不适合。- directsync(直接同步)
此模式会导致超级管理程序使用
O_DSYNC
和O_DIRECT
语义来与磁盘映像文件或块设备交互。这意味着,仅当已将数据提交到储存设备,同时还需要绕过主机页缓存时,才将写入操作报告为已完成。与 writethrough(直写) 一样,此模式对于不按需发送刷新命令的 Guest 很有用。它是新增的最后一种缓存模式,补全了缓存和直接访问语法的可能组合。
17.3 缓存模式对数据完整性的影响 #
- writethrough、none、directsync
这些是最安全的模式。如果 Guest 操作系统是“新式版本且行为正常”(即,可按需使用刷新命令),则认为这三种模式是同等安全的。如果您怀疑 Guest 的安全性,请使用 writethough 或 directsync。请注意,某些文件系统与
none
或directsync
不兼容,因为它们不支持这些缓存模式所依赖的 O_DIRECT。- writeback
此模式告知 Guest 存在写入缓存,并依赖于 Guest 按需发送刷新命令来维持其磁盘映像中的数据完整性。这是新式文件系统中充分纳入考虑的一种常见储存设计。此模式会使 Guest 在主机发生故障时(不太可能发生)面临数据丢失的风险,因为将写入操作报告为已完成与将写入内容提交到储存设备之间存在时间差。
- unsafe
此模式与 writeback 缓存类似,只不过存在以下差别:将忽略 Guest 刷新命令,因而消除了这些刷新命令的数据完整性控制作用,导致因主机故障而造成的数据丢失风险增大。应该将“unsafe”(不安全)这一名称视为一种警告,与其他模式相比,使用此模式在主机发生故障时丢失数据的概率要高得多。Guest 终止时,缓存的数据会随即刷新。
17.4 缓存模式对性能的影响 #
充分利用页缓存、直写页缓存或者完全绕过页缓存的选项可能会对性能产生重大影响。其他影响磁盘性能的因素包括实际的储存系统的功能、使用的磁盘映像格式、页缓存的潜在大小,以及使用的 IO 调度程序。此外,不刷新写入缓存可提高性能,但也会带来上面所述的风险。一般而言,高端系统在使用缓存模式 none
时通常可以获得最佳性能,因为此模式减少了需进行的数据复制操作。此外,还应该考虑到让多个 Guest 共享通用主机页缓存可能带来的优势,读写比例以及 AIO 模式 native
的使用(参见下文)。
17.5 缓存模式对实时迁移的影响 #
缓存储存数据和元数据会限制支持实时迁移的配置。目前,只能使用 raw
和 qcow2
映像格式进行实时迁移。如果使用群集文件系统,则所有缓存模式都支持实时迁移。否则,只有 none
缓存模式支持在读取/写入共享储存中进行实时迁移。
libvirt
管理层包含根据多种因素检查迁移兼容性的功能。如果 Guest 储存托管在群集文件系统上,并且是只读的或者标记为可共享,则在确定是否允许迁移时会忽略缓存模式。除非将缓存模式设置为 none
,否则 libvirt
不允许迁移。不过,您可以通过在迁移 API 中使用“unsafe”选项来覆盖此限制,此选项也受 virsh
的支持,如下面的示例所示
tux >
virsh migrate --live --unsafe
要设置 AIO 模式 native
,缓存模式需设为 none
。如果使用另一种缓存模式,则 AIO 模式将无提示切换回默认值 threads
。主机中的 Guest 刷新通过 fdatasync()
来实现。