优化永久性磁盘和本地 SSD 的性能

永久性磁盘因其价格实惠、性能优异并且可预测性好而成为最常见的存储选项。但是,您可以使用本地 SSD 来创建实例,以获得更高的性能和更低的延迟,只是这样就无法获得永久性磁盘的数据冗余性和耐用性。在您为实例上运行的应用配置存储选项时,请使用以下流程:

  • 确定您需要多少空间。
  • 确定您的应用所需的性能特征。
  • 配置实例以优化存储性能。

本文档将讨论您可以附加到 Compute Engine 实例的块存储选项。要查看 Google Cloud Platform 上的存储选项的完整列表,请阅读选择存储选项

块存储性能比较

请考虑您的存储空间大小和性能要求,这样有助于您确定适用于您实例的正确磁盘类型和大小。一个给定应用的性能要求通常分为两种不同的 I/O 模式。

  • 小批量读写操作
  • 大批量读写操作

对于小批量读写操作,其限制因素是随机的每秒输入/输出操作次数 IOPS

对于大批量读写操作,其限制因素是吞吐量

地区
标准
永久性磁盘
区域
标准
永久性磁盘
地区
SSD
永久性磁盘
区域
SSD
永久性磁盘
本地 SSD (SCSI) 本地 SSD (NVMe)
最大持续 IOPS
读取 IOPS/GB 0.75 0.75 30 30 266.7 453.3
写入 IOPS/GB) 1.5 1.5 30 30 186.7 240
读取 IOPS/实例 3,000* 3,000* 15,000 - 60,000* 15,000 - 60,000* 400,000 680,000
写入 IOPS/实例 15,000* 15,000* 15,000 - 30,000* 15,000 - 30,000* 280,000 360,000
最大持续吞吐量 (MB/s)
读取吞吐量/GB 0.12 0.12 0.48 0.48 1.04 1.77
写入吞吐量/GB 0.12 0.12 0.48 0.48 0.73 0.94
读取吞吐量/实例 180* 180* 240 - 1200* 240 - 1200* 1,560 2,650
写入吞吐量/实例 76-120** 38-120** 76 - 400* 38 - 200* 1,090 1,400

* 永久性磁盘 IOPS 和吞吐量性能取决于实例 vCPU 的数量和 IO 块大小。请参阅 SSD 永久性磁盘性能限制了解有关 SSD 永久性磁盘的详情,并请参阅标准永久性磁盘性能限制了解有关标准永久性磁盘的详情。

** SSD 和标准永久性磁盘可以在具有更多 vCPU 的实例上实现更高的吞吐量性能。有关详细信息,请参阅针对写入吞吐量的网络出站流量上限

将永久性磁盘与物理硬盘进行比较

在您指定永久性磁盘的容量大小时,请考虑这些磁盘与传统物理硬盘之间的对比情况。下表将标准永久性磁盘和 SSD 永久性磁盘与 7200 RPM SATA 硬盘的典型性能进行了比较,后者通常可达到 75 IOPS 或 120 MB/秒。

I/O 类型 I/O 模式 要达到与 7200 RPM SATA 硬盘同等的性能所需的容量大小
标准永久性磁盘 SSD 永久性磁盘
小批量随机读取次数 75 次小批量随机读取 100 GB 3 GB
小批量随机写入次数 75 次小批量随机写入 50 GB 3 GB
流式大批量读取 120 MB/秒的流式读取 1000 GB 250 GB
流式大批量写入 120 MB/秒的流式写入 1000 GB 250 GB

容量大小、价格和性能摘要

虽然您在为应用选择卷类型和大小时需要考虑若干因素,但您不需要考虑的一个因素就是卷的使用费用。永久性磁盘不是根据 I/O 数据量来计费的,因此您无需通过估算每月 I/O 数据量来计算将要用在磁盘上的预算。

以下价格计算示例使用的是美国永久性磁盘价格。在这些示例中,请只考虑标准永久性磁盘与 SSD 永久性磁盘相比较的相对成本。标准永久性磁盘的价格为每 GB $0.040,而 SSD 永久性磁盘的价格为每 GB $0.170。但是,性能上限会随着卷的大小而增加,因此对于面向 IOPS 的工作负载,请查看每次 IOPS 的价格。

标准永久性磁盘的每次随机读取 IOPS 约为 $0.053,每次随机写入 IOPS 约为 $0.0266。SSD 永久性磁盘的每次随机读取 IOPS 为 $0.0057,每次随机写入 IOPS 为 $0.0057。在 SSD 永久性磁盘达到实例的 IOPS 限制或该实例的 vCPU 数量之前,上述每次 IOPS 的价格都是适用的。

SSD 永久性磁盘在 2000 GB 时达到 60000 次随机读取 IOPS 的上限,在 1000 GB 时达到 30000 次随机写入 IOPS 的上限。相比之下,标准永久性磁盘在 4 TB 时达到 3000 次随机读取 IOPS 的上限,在 10 TB 时达到 15000 次随机写入 IOPS 的上限。

SSD 永久性磁盘的设计旨在确保将延迟时间控制在数毫秒以内。实际的延迟时间取决于具体的应用。

标准永久性磁盘

标准永久性磁盘的性能可线性扩展至虚拟机性能上限。实例的 vCPU 数量不会限制标准永久性磁盘的性能。

如果您的实例的 vCPU 数量为 4 个或更多,这并不会限制标准永久性磁盘的性能。如果您的实例的 vCPU 数量少于 4 个,则写入上限将会减少,特别是在 IOPS 方面,因为它受限于与 vCPU 数量成正比的网络出站流量限制,还取决于 IO 的大小(在同一 IOPS 级别,16 KB IO 消耗的带宽比 8 KB IO 多)。

标准永久性磁盘的 IOPS 和吞吐量性能会随着磁盘容量大小线性增加,直到达到以下上限(按每个实例计算):

  • 读取吞吐量:磁盘容量大小为 1.5 TB 时最高可达到 180 MB/秒。
  • 写入吞吐量:磁盘容量大小为 1 TB 时最高可达到 120 MB/秒。
  • 读取 IOPS:磁盘容量大小为 4 TB 时最高可达到 3000 次 IOPS。
  • 写入 IOPS:磁盘容量大小为 10 TB 时最高可达到 15000 次 IOPS。

要在现有的实例中获得永久性磁盘的性能优势,请调整永久性磁盘的大小以增加每块永久性磁盘的 IOPS 和吞吐量。

卷大小 (GB) 持续随机 IOPS 持续吞吐量(MB/秒)
读取
(<=16 KB/IO)
写入
(<=8 KB/IO)
写入
(16 KB/IO)
读取 写入
10 * * * * *
32 24 48 48 3 3
64 48 96 96 7 7
128 96 192 192 15 15
256 192 384 384 30 30
512 384 768 768 61 61
1000 750 1500 1500 120 120
1500 1125 2250 2250 180 120
2048 1536 3072 3072 180 120
4000 3000 6000 6000 180 120
5000 3000 7500 7500 180 120
8192 3000 12288 7500 180 120
10000 3000 15000 7500 180 120
16384 3000 15000 7500 180 120
32768 3000 15000 7500 180 120
65536 3000 15000 7500 180 120

* 只能针对启动卷使用此卷大小。要想完成任何有意义的任务,都将依赖于 I/O 爆发。

SSD 永久性磁盘

与标准永久性磁盘不同,SSD 永久性磁盘的 IOPS 性能取决于实例中的 vCPU 数量。

SSD 永久性磁盘的性能可线性扩展,直到达到卷的性能上限或相应 Compute Engine 实例的性能上限。SSD 读取带宽和/或接近上限的 IOPS 一致性在很大程度上取决于网站入站流量利用率;预计会发生一些变动,特别是对于接近 IOPS 上限的 16 KB IO。请参阅下表以了解详细信息。注意:您可能会注意到,由于持续改进,每个实例的 SSD 永久性磁盘写入吞吐量超出已发布的上限。

实例的 vCPU 数量 持续随机 IOPS 持续吞吐量(MB/秒)
读取
(<=16 KB/IO)
写入
(<=8 KB/IO)
写入
(16 KB/IO)
读取* 写入
1 到 3 个 vCPU15000 15000 4500/vCPU 240 240
4 到 7 个 vCPU 15000 15000 15000 240 240
8 到 15 个 vCPU 15000 15000 15000 800 240
16 到 31 个 vCPU 25000 25000 15000 1200 240
32 到 63 个 vCPU 60,000 30000 25000 1200 400
64 个及更多 vCPU** 60000 30000 25000 1200 400

* 基于 IO 块大小为 256 KB 或更大值的吞吐量最大值。

** 在 CPU 完全被占用的情况下,可能无法实现最高性能。

要提高现有实例上的 SSD 永久性磁盘的性能,请更改实例的机器类型以增加每个虚拟机的性能上限,并调整永久性磁盘的大小以增加每个永久性磁盘的 IOPS 和吞吐量。

卷大小 (GB) 持续随机 IOPS 持续吞吐量(MB/秒)
读取
(<=16 KB/IO)
写入
(<=8 KB/IO)
写入
(16 KB/IO)
读取 写入
10 300 300 300 4.8 4.8
32 960 960 960 15 15
64 1920 1920 1920 30 30
128 3840 3840 3840 61 61
256 7680 7680 7680 122 122
500 15000 15000 15000 240 240
834 25000 25000 25000 400 400
1000 30000 30000 25000 480 400
1334 40000 30000 25000 640 400
1667 50000 30000 25000 800 400
2048 60000 30000 25000 983 400
4096 60000 30000 25000 1200 400
8192 60000 30000 25000 1200 400
16384 60000 30000 25000 1200 400
32768 60000 30000 25000 1200 400
65536 60000 30000 25000 1200 400

同时读取和写入

对于标准永久性磁盘,同时发生的读取和写入操作共享相同的性能上限。当您的实例使用了更多的读取吞吐量或 IOPS 时,它能够执行的写入次数就会更少。如果实例使用了更多的写入吞吐量,那么它能够执行的读取次数也会减少。

SSD 永久性磁盘则可以同时达到读取和写入操作的吞吐量上限。但是,对于 IOPS 性能,SSD 永久性磁盘无法同时达到其最大读取和写入上限。要在同时执行读取和写入操作期间实现最大吞吐量上限,请优化您的 I/O 大小,以使卷能够达到其吞吐量上限,而又不至于遇到 IOPS 瓶颈。

适用于同时读取和写入的实例 IOPS 上限:

下表中的 IOPS 数字基于 8 KB IO 大小。其他 IO 大小(如 16 KB)可能具有不同的 IOPS 数字,但将具有相同的读取/写入分配。

标准永久性磁盘 SSD 永久性磁盘(8 个 vCPU) SSD 永久性磁盘(32 个或更多 vCPU)
读取 写入 读取 写入 读取 写入
3000 IOPS 0 IOPS 15000 IOPS 0 IOPS 60000 IOPS 0 IOPS
2250 IOPS 3750 IOPS 11250 IOPS 3750 IOPS 45000 IOPS 7500 IOPS
1500 IOPS 7500 IOPS 7500 IOPS 7500 IOPS 30000 IOPS 15000 IOPS
750 IOPS 11250 IOPS 3750 IOPS 11250 IOPS 15000 IOPS 22500 IOPS
0 IOPS 15000 IOPS 0 IOPS 15000 IOPS 0 IOPS 30000 IOPS

适用于同时读取和写入的实例吞吐量上限:

标准永久性磁盘 SSD 永久性磁盘(8 个 vCPU) SSD 永久性磁盘(32 个或更多 vCPU)
读取 写入 读取 写入 读取 写入
180 MB/秒 0 MB/秒 240 MB/秒 240 MB/秒 1200 MB/秒* 400 MB/秒*
135 MB/秒 30 MB/秒
90 MB/秒 60 MB/秒
45 MB/秒 90 MB/秒
0 MB/秒 120 MB/秒

* 对于 SSD 永久性磁盘,读取吞吐量最大值和写入吞吐量最大值彼此独立,因此这些上限是不变的。您可能会注意到,由于持续改进,每个实例的 SSD 永久性磁盘写入吞吐量超出已发布的上限。

针对写入吞吐量的网络出站流量上限

每个永久性磁盘写入操作都会占用虚拟机实例的累计网络出站流量限额

要计算某个虚拟机实例可以发送的永久性磁盘最大写入流量,请从该实例的每个 vCPU 每秒 2 Gbit 的网络流量上限中减去其他网络出站流量。剩余的吞吐量就表示您可以用于永久性磁盘写入流量的吞吐量。

Compute Engine 将数据存储在永久性磁盘上,以使其具有内置冗余性。实例通过将数据并行写入永久性磁盘三次来实现此冗余。此外,每个写入请求都有一定的开销,因为占用了出站流量带宽。

每个虚拟机实例都有一个永久性磁盘写入上限,具体取决于该虚拟机的网络出站流量上限。例如,以下数据来自于某个没有任何额外 IP 流量的实例。

标准永久性磁盘 固态永久性磁盘
vCPU 的数量 标准永久性磁盘的写入上限(MB/秒) 达到上限所需的标准卷大小 (GB) SSD 永久性磁盘的写入上限(MB/秒) 达到上限所需的 SSD 永久性磁盘大小 (GB)
1 78 650 78 163
2 120 1000 156 326
4 120 1000 240 500
8 120 1000 240 500
16 120 1000 240 500
32+ 120 1000 400 1000

要了解此表格中的值是如何计算得出的,请参考一个简单的示例(其中包含 1 个 vCPU 和标准永久性磁盘)。在此示例中,我们估计每个写入请求的带宽系数是 3.3,这意味着数据被向外写出了 3 次,并且总开销为 10%。要计算出站流量上限,请将网络出站流量上限 2 Gbit/秒(相当于 256 MB/秒)除以 3.3:

一个 vCPU 的最大写入带宽 = 256 / 3.3 = ~78 MB/秒(写入到您的标准永久性磁盘)

此外,使用前面介绍的性能图表中提供的标准永久性磁盘的写入吞吐量/GB 数据,您现在就可以计算得到实现上述性能所需的磁盘容量:

1 个 vCPU 要达到最大写入带宽所需的磁盘容量 = 78 / 0.12 = ~650 GB

与地区永久性磁盘类似,来自区域永久性磁盘的写入流量也会占用虚拟机实例的累计网络出站流量上限。要计算适用于区域永久性磁盘的网络出站流量上限,请使用系数 6.6,而不是用于地区永久性磁盘的系数 3.3。

一个 vCPU 的最大写入带宽 = 256 / 6.6 = ~39 MB/秒(写入到复制的标准永久性磁盘)。

优化永久性磁盘和本地 SSD 的性能

您可以对永久性磁盘和本地 SSD 进行优化,以便更高效地处理您的数据。

优化永久性磁盘

永久性磁盘可以为您提供磁盘类型图表中描述的性能,但虚拟机必须具有足够的使用率才能达到这些性能上限。在您根据性能需求适当调整永久性磁盘卷大小后,您的应用和操作系统可能需要进行一些细微调整。

在本部分中,我们将介绍几个可以进行调整以获得更好性能的关键因素,并讨论如何将其中一些因素应用于特定类型的工作负载。

停用延迟初始化并启用 DISCARD 命令

永久性磁盘支持 DISCARD 或 TRIM 命令,借助这些命令,操作系统就能在磁盘块不再被使用时通知磁盘。对 DISCARD 命令的支持可以让操作系统将磁盘块标记为不再需要,而不会产生将块清零的费用。

在大多数 Linux 操作系统上,您可以在将某块永久性磁盘装载到实例后启用 DISCARD。当您装载永久性磁盘时,Windows 2012 R2 实例会默认启用 DISCARD。Windows 2008 R2 不支持 DISCARD。

启用 DISCARD 不仅可以改善一般运行时性能,而且还可以提高磁盘在首次装载后的性能。对整个磁盘卷进行格式化可能会非常耗时。因此,一种常见的做法就是所谓的“延迟格式化”。延迟格式化的缺点是,通常要在第一次装载卷时支付费用。通过停用延迟初始化并启用 DISCARD 命令,您可以快速地执行格式化和装载。

  • 通过将以下参数传递给 mkfs.ext4,即可停用延迟初始化并在格式化过程中启用 DISCARD:

    -E lazy_itable_init=0,lazy_journal_init=0,discard
    

    lazy_journal_init=0 参数不适用于具有 CentOS 6RHEL 6 映像的实例。对于这些实例,在格式化永久性磁盘时请不要使用该参数。

    -E lazy_itable_init=0,discard
    
  • 在装载时启用 DISCARD 命令,将以下标志传递给 mount 命令:

    -o discard
    

永久性磁盘在启用了 discard 选项后就能运行良好。但是,您也可以不使用 discard 选项,而选择定期运行 fstrim,或者同时运用这两种方式。如果您不使用 discard 选项,请在创建磁盘快照之前运行 fstrim。裁剪文件系统可让您创建的快照映像更小,从而减少存储快照的费用。

I/O 队列深度

许多应用的设置都可以通过影响其 I/O 队列深度来调整性能。较大的队列深度可增加 IOPS,但也会增加延迟时间。较小的队列深度会降低每次 I/O 的延迟时间,但有时会牺牲 IOPS 性能。

预读缓存

为了提高 I/O 性能,操作系统使用了如 readahead(预读)等技术,该技术假定后续读取可能需要文件中的某些数据,因此会将该文件中的更多内容读入内存,而不只是所请求的部分。较高的 readahead 值可增加吞吐量,但是会占用更多内存和 IOPS。较低的 readahead 值可增加 IOPS,但是会牺牲吞吐量。

在 Linux 系统上,您可以使用 blockdev 命令获取和设置 readahead 值:

$ sudo blockdev --getra /dev/[DEVICE_ID]
$ sudo blockdev --setra [VALUE] /dev/[DEVICE_ID]

readahead 值为 <desired_readahead_bytes> / 512 字节。

例如,如果您需要 8 MB 的预读数据量(8 MB 就是 8388608 字节 (8 * 1024 * 1024)),

8388608 bytes / 512 bytes = 16384

那么您可以进行如下设置:

$ sudo blockdev --setra 16384 /dev/[DEVICE_ID]

让 CPU 有空闲时间

读取和写入永久性磁盘都需要使用虚拟机提供的 CPU 周期。要实现非常高而且一致的 IOPS 级别,需要让 CPU 能够有空闲时间来处理 I/O 操作。

面向 IOPS 的工作负载

无论是 SQL 数据库还是 NoSQL 数据库都具有随机访问数据的使用模式。对于面向 IOPS 的工作负载,我们建议采用以下做法:

  • MongoDBApache Cassandra 和其他数据库应用的最佳做法文档中通常建议使用较低的 readahead 值

  • 每 400-800 次 IOPS 的 I/O 队列深度值为 1,对于容量较大的卷而言上限为 64

  • 针对每 2000 次随机读取 IOPS 使用 1 个空闲 CPU,针对每 2500 次随机写入 IOPS 使用 1 个空闲 CPU

面向吞吐量的工作负载

流式传输操作(例如 Hadoop 作业)可受益于快速顺序读取。因此,较大的磁盘块大小可以提高流式传输的性能。卷上的默认块大小为 4K。对于面向吞吐量的工作负载,我们建议使用 256KB 或更大的值。

优化 SSD 永久性磁盘的性能

各种磁盘类型的性能图表中描述了固态永久性磁盘的预期可实现的性能上限。要优化应用和虚拟机实例以达到这些处理速度,请使用以下最佳做法:

  • 确保您的应用发出足够的 I/O 操作

    如果您的应用发出的 IOPS 数量少于以上图表中描述的上限,则您将无法达到该 IOPS 级别。例如,在一块 500 GB 的磁盘上,预期的 IOPS 上限为 15000 IOPS。但是,如果应用发出的 IOPS 数量少于该值,或者发出的 I/O 操作的数据量超过了 8 KB,则将无法达到 15000 IOPS。

  • 确保以足够的并行性发出 I/O 操作

    使用足够大的队列深度,您可以利用操作系统的并行性。如果您发出 1000 IOPS,但以队列深度为 1 的同步方式执行此操作,则所能达到的 IOPS 将远远低于图表中描述的上限。针对每 400-800 IOPS,您的应用的队列深度至少应为 1。

  • 确保发出 I/O 的虚拟机实例上有足够使用的 CPU

    如果您的虚拟机实例缺乏 CPU,则您的应用将无法管理上述 IOPS。根据经验,您应该针对每 2000-2500 IOPS 的预期流量准备一个可用的 CPU。

  • 确保您的应用已针对大容量磁盘上合理的时态数据位置进行了优化

    如果您的应用在短时间内访问分布于某块磁盘不同部分的数据(每个 vCPU 数百 GB),则无法实现最佳 IOPS。要获得最佳性能,请针对时态数据位置进行优化,并权衡各种因素(如磁盘碎片和磁盘被访问部分的随机性)。

  • 确保对操作系统中的 I/O 调度程序进行配置以满足您的特定需求

    在基于 Linux 的系统上,您可以将 I/O 调度程序设置为 noop,以在基于 SSD 的设备上实现最大 IOPS。

对 SSD 永久性磁盘的性能进行基准化分析

下面的命令假设有一个 2500 GB 容量的设备,如果您设备的容量大小不同,请修改 --filesize 参数。此磁盘大小是实现当前 32 个vCPU 虚拟机吞吐量限制所必需的。

    # Install dependencies
    sudo apt-get update
    sudo apt-get install -y fio
  1. 使用非零数据填充磁盘。对于永久性磁盘而言,从空白的磁盘块读取内容的延迟配置文件与包含数据的磁盘块不同。我们建议您在运行任何读取延迟基准化分析之前先填充磁盘。

    # Running this command will cause you to lose data on the second device.
    # We strongly recommend using a throwaway VM and disk.
    sudo fio --name=fill_disk \
      --filename=/dev/sdb --filesize=2500G \
      --ioengine=libaio --direct=1 --verify=0 --randrepeat=0 \
      --bs=128K --iodepth=64 --rw=randwrite
    
  2. 测试写入带宽。

    # Running this command will cause you to lose data on the second device.
    # We strongly recommend using a throwaway VM and disk.
    sudo fio --name=write_bandwidth_test \
      --filename=/dev/sdb --filesize=2500G \
      --time_based --ramp_time=2s --runtime=1m \
      --ioengine=libaio --direct=1 --verify=0 --randrepeat=0 \
      --bs=1M --iodepth=32 --rw=randwrite
    
  3. 测试写入 IOPS。要达到永久性磁盘的 IOPS 上限,维护一个较深的 IO 队列是非常重要的。例如,如果写入延迟时间为 1 毫秒,则对于每个正在执行的 IO,虚拟机最多可以达到 1000 IOPS。要达到 15000 IOPS,虚拟机必须维护至少 15 个正在执行的 IO。如果您的磁盘和虚拟机能够达到 30000 IOPS,则正在执行的 IO 数量必须至少有 30 个。如果 IO 大小超过 4 KB,则虚拟机在达到 IOPS 上限之前可能会先达到带宽上限。

    # Running this command will cause you to lose data on the second device.
    # We strongly recommend using a throwaway VM and disk.
    sudo fio --name=write_iops_test \
      --filename=/dev/sdb --filesize=2500G \
      --time_based --ramp_time=2s --runtime=1m \
      --ioengine=libaio --direct=1 --verify=0 --randrepeat=0 \
      --bs=4K --iodepth=64 --rw=randwrite
    
  4. 测试写入延迟时间。在测试 IO 延迟时间时,请务必不要让虚拟机达到带宽或 IOPS 上限,否则延迟时间将无法反映出实际的永久性磁盘 IO 延迟时间。例如:如果在 IO 深度为 30 时达到了 IOPS 上限,并且 fio 命令已将其加倍,则总 IOPS 将保持不变,并且所报告的 IO 延迟时间将加倍。

    # Running this command will cause you to lose data on the second device.
    # We strongly recommend using a throwaway VM and disk.
    sudo fio --name=write_latency_test \
      --filename=/dev/sdb --filesize=2500G \
      --time_based --ramp_time=2s --runtime=1m \
      --ioengine=libaio --direct=1 --verify=0 --randrepeat=0 \
      --bs=4K --iodepth=4 --rw=randwrite
    
  5. 测试读取带宽。

    sudo fio --name=read_bandwidth_test \
      --filename=/dev/sdb --filesize=2500G \
      --time_based --ramp_time=2s --runtime=1m \
      --ioengine=libaio --direct=1 --verify=0 --randrepeat=0 \
      --bs=256K --iodepth=64 --rw=randread
    
  6. 测试读取 IOPS。要达到永久性磁盘的 IOPS 上限,维护一个足够深的 IO 队列是非常重要的。如果 IO 大小超过 4 KB,则虚拟机在达到 IOPS 上限之前可能会先达到带宽上限。

    sudo fio --name=read_iops_test \
      --filename=/dev/sdb --filesize=2500G \
      --time_based --ramp_time=2s --runtime=1m \
      --ioengine=libaio --direct=1 --verify=0 --randrepeat=0 \
      --bs=4K --iodepth=64 --rw=randread
    
  7. 测试读取延迟时间。请务必用数据填充磁盘,以获得真实的延迟时间测量结果。在此测试期间,请确保不要让虚拟机达到 IOPS 或吞吐量上限。一旦永久性磁盘达到其饱和上限,它将拒绝传入的 IO,这将反映为 IO 延迟时间的人为增加。

    sudo fio --name=read_latency_test \
      --filename=/dev/sdb --filesize=2500G \
      --time_based --ramp_time=2s --runtime=1m \
      --ioengine=libaio --direct=1 --verify=0 --randrepeat=0 \
      --bs=4K --iodepth=4 --rw=randread
    
  8. 测试顺序读取带宽。

    sudo fio --name=read_bandwidth_test \
      --filename=/dev/sdb --filesize=2500G \
      --time_based --ramp_time=2s --runtime=1m \
      --ioengine=libaio --direct=1 --verify=0 --randrepeat=0 \
      --numjobs=4 --thread --offset_increment=500G \
      --bs=1M --iodepth=16 --rw=read
    

优化本地 SSD

各种磁盘类型的性能图表中描述了本地 SSD 设备的预期可实现的性能上限。要优化应用和虚拟机实例以达到这些处理速度,请使用以下最佳做法:

对本地 SSD 使用 Linux 访客环境优化功能

默认情况下,大多数由 Compute Engine 提供的 Linux 映像将自动运行一个优化脚本,该脚本会对实例进行配置以实现本地 SSD 的最大性能。该脚本启用了某些队列 sysfs 文件设置,这些设置可增强机器的整体性能,并屏蔽对某些特定虚拟 CPU (vCPU) 的中断请求 (IRQ)。此脚本只针对 Compute Engine 本地 SSD 设备进行性能优化。

Ubuntu、SLES 和较旧的映像可能未配置为包含此性能优化功能。如果您正在使用这些映像中的任何一个或者 v20141218 之前的映像,则可以安装 Linux 访客环境来启用这些优化功能。

为 NVMe 或 SCSI 接口选择最佳映像

本地 SSD 在采用 NVMe 或 SCSI 接口类型时运行得最好,具体取决于您在实例的启动磁盘上使用的映像。 为您的本地 SSD 设备选择一个最适合您的启动磁盘映像的接口。如果您的实例使用 SCSI 接口连接到本地 SSD,则可以在来宾操作系统上启用多队列 SCSI,以通过 SCSI 接口实现最佳性能。

在具有自定义映像和本地 SSD 的实例上启用多队列 SCSI

某些公开映像可支持多队列 SCSI。如果您需要在导入到项目中的自定义映像上具备多队列 SCSI 功能,则必须自行启用该功能。只有包含内核版本 3.19 或更高版本的导入的 Linux 映像才能使用多队列 SCSI。

要在某个自定义映像上启用多队列 SCSI,请在启用了 VIRTIO_SCSI_MULTIQUEUE 来宾操作系统功能的情况下导入该映像,并向 GRUB 配置文件中添加一个条目:

CentOS

仅适用于 CentOS7。

  1. 使用 API 导入您的自定义映像,并添加一个 type 值为 VIRTIO_SCSI_MULTIQUEUEguestOsFeatures 项。

  2. 使用您的自定义映像创建一个实例,并附加一个或多个本地 SSD

  3. 通过 SSH 连接到您的实例

  4. 查看 /sys/module/scsi_mod/parameters/use_blk_mq 文件的值

    $ cat /sys/module/scsi_mod/parameters/use_blk_mq
    

    如果此文件的值为 Y,则说明在导入的映像上已启用多队列 SCSI。如果此文件的值为 N,请在 GRUB 配置文件内的 GRUB_CMDLINE_LINUX 条目中添加 scsi_mod.use_blk_mq=Y,并重启系统。

    1. 在文本编辑器中打开 /etc/default/grub GRUB 配置文件。

      $ sudo vi /etc/default/grub
      
    2. scsi_mod.use_blk_mq=Y 添加到 GRUB_CMDLINE_LINUX 条目中。

      GRUB_CMDLINE_LINUX=" vconsole.keymap=us console=ttyS0,38400n8 vconsole.font=latarcyrheb-sun16 scsi_mod.use_blk_mq=Y"
      
    3. 保存配置文件。

    4. 运行 grub2-mkconfig 命令即可重新生成 GRUB 文件并完成配置。

      $ sudo grub2-mkconfig -o /boot/grub2/grub.cfg
      
    5. 重启实例。

      $ sudo reboot
      

Ubuntu

  1. 使用 API 导入您的自定义映像,并添加一个 type 值为 VIRTIO_SCSI_MULTIQUEUEguestOsFeatures 项。

  2. 使用您的自定义映像创建一个实例,并使用 SCSI 接口附加一个或多个本地 SSD

  3. 通过 SSH 连接到您的实例

  4. 查看 /sys/module/scsi_mod/parameters/use_blk_mq 文件的值。

    $ cat /sys/module/scsi_mod/parameters/use_blk_mq
    

    如果此文件的值为 Y,则说明在导入的映像上已启用多队列 SCSI。如果此文件的值为 N,请在 GRUB 配置文件内的 GRUB_CMDLINE_LINUX 条目中添加 scsi_mod.use_blk_mq=Y,并重启系统。

    1. 在文本编辑器中打开 sudo nano /etc/default/grub GRUB 配置文件。

      $ sudo nano /etc/default/grub
      
    2. scsi_mod.use_blk_mq=Y 添加到 GRUB_CMDLINE_LINUX 条目中。

      GRUB_CMDLINE_LINUX="scsi_mod.use_blk_mq=Y"
      
    3. 保存配置文件。

    4. 运行 update-grub 命令即可重新生成 GRUB 文件并完成配置。

      $ sudo update-grub
      
    5. 重启实例。

      $ sudo reboot
      

停用写入缓存刷新功能

文件系统、数据库和其他应用会使用缓存刷新功能来确保在各个检查点将数据提交到耐用的存储系统中。对于大多数存储设备来说,这种默认操作是有意义的。但是,本地 SSD 上的写入缓存刷新速度相当缓慢。您可以通过在这些应用中停用自动刷新命令或通过在文件系统级别停用刷新选项来提高某些应用的写入性能。

无论您为文件系统和应用设置的刷新命令是怎样的,本地 SSD 总是会在两秒钟内刷新已缓存的写入内容,因此临时硬件故障最多只会导致您丢失两秒钟的缓存写入内容。无论是否已刷新数据,永久性的硬件故障仍可能导致设备上的所有数据丢失,因此您仍应将关键数据备份到永久性磁盘Cloud Storage 存储分区中。

要在 ext4 文件系统上停用写入缓存刷新功能,请在您的装载选项或 /etc/fstab 条目中添加 nobarrier。例如:

$ sudo mount -o discard,defaults,nobarrier /dev/[LOCAL_SSD_ID] /mnt/disks/[MNT_DIR]

其中:[LOCAL_SSD_ID] 是您要装载的本地 SSD 的设备 ID。

对本地 SSD 的性能进行基准化分析

“性能”部分中提供的本地 SSD 性能数据是通过在本地 SSD 实例上使用特定的设置而得到的。如果您的实例无法达到这些性能上限,并且您已经按照建议的本地 SSD 设置配置了实例,则可以通过复制 Compute Engine 团队所使用的设置,将您的性能上限与已发布的上限进行比较。

  1. 创建一个本地 SSD 实例,该实例针对每个设备具有四个或八个 vCPU,具体取决于您的工作负载。例如,如果您要将四个本地 SSD 设备附加到一个实例,请使用具有 16 或 32 个 vCPU 的机器类型。

    以下命令将创建一个具有 8 个 vCPU 和一个本地 SSD 的虚拟机:

    gcloud compute instances create ssd-test-instance \
    --machine-type "n1-standard-8" \
    --local-ssd interface="SCSI"
    
  2. 在您的机器上运行以下脚本,该脚本将复制用于达到上述速度的设置。请注意,--bs 参数定义了磁盘块的大小,此块大小会影响不同类型的读写操作的结果。

    # install dependencies
    sudo apt-get update -y
    sudo apt-get install -y build-essential git libtool gettext autoconf \
    libgconf2-dev libncurses5-dev python-dev fio bison autopoint
    
    # blkdiscard
    git clone https://git.kernel.org/pub/scm/utils/util-linux/util-linux.git
    cd util-linux/
    ./autogen.sh
    ./configure --disable-libblkid
    make
    sudo mv blkdiscard /usr/bin/
    sudo blkdiscard /dev/disk/by-id/google-local-ssd-0
    
    # full write pass - measures write bandwidth with 1M blocksize
    sudo fio --name=writefile --size=100G --filesize=100G \
    --filename=/dev/disk/by-id/google-local-ssd-0 --bs=1M --nrfiles=1 \
    --direct=1 --sync=0 --randrepeat=0 --rw=write --refill_buffers --end_fsync=1 \
    --iodepth=200 --ioengine=libaio
    
    # rand read - measures max read IOPS with 4k blocks
    sudo fio --time_based --name=benchmark --size=100G --runtime=30 \
    --filename=/dev/disk/by-id/google-local-ssd-0 --ioengine=libaio --randrepeat=0 \
    --iodepth=128 --direct=1 --invalidate=1 --verify=0 --verify_fatal=0 \
    --numjobs=4 --rw=randread --blocksize=4k --group_reporting
    
    # rand write - measures max write IOPS with 4k blocks
    sudo fio --time_based --name=benchmark --size=100G --runtime=30 \
    --filename=/dev/disk/by-id/google-local-ssd-0 --ioengine=libaio --randrepeat=0 \
    --iodepth=128 --direct=1 --invalidate=1 --verify=0 --verify_fatal=0 \
    --numjobs=4 --rw=randwrite --blocksize=4k --group_reporting
    

后续步骤

此页内容是否有用?请给出您的反馈和评价:

发送以下问题的反馈:

此网页
Compute Engine 文档