SSD Nodes Learn 8GB 内存 — 每年 $66
指南 Matt Connor作者: Matt Connor · 更新于 2026-08-01

NVMe 与 SSD VPS 有什么区别,值得升级吗?

NVMe 在高并发小块读写中可降低延迟并提升 IOPS,但 VPS 性能还取决于虚拟机监控程序和邻居负载。用 fio 测量您的实际结果。

NVMe 对 VPS 重要吗?

当软件发送大量小型读写请求,并等待每个请求完成时,NVMe 对 VPS 很重要。对于提供缓存页面的网站,或大部分时间都在等待网络的程序,NVMe 的影响很小。存储介质只是其中一个因素。磁盘前的虚拟机监控程序,以及共享同一主机的其他虚拟机,决定了您实际获得的性能上限。

NVMe 的变化及其不变之处

NVMe(非易失性内存标准)不是一种闪存。它是访问闪存所使用的协议和连接方式。NVMe 设备通过 PCIe(外围组件互连高速)通道连接,并使用 NVMe 协议通信。SATA(串行 ATA)SSD 通过 SATA 链路连接,并使用 AHCI(高级主机控制器接口)协议通信。两者用于存储数据的内存芯片可能完全相同。

两者有两项差异,但差异都在命令路径,而不是存储介质本身。

队列。 AHCI 为内核提供一个可容纳 32 个命令的命令队列。NVMe 支持数千个队列,实际使用中通常每个 CPU 核心一个队列,而且每个队列的深度都远大于 32。单个进程每次只读取一个块时,无法感知这一差异。数据库同时发出 64 个待读取请求时则可以:在 SATA 上,第 33 个请求必须等待队列槽位,设备甚至还看不到它;而 NVMe 设备会接受全部请求并同时处理。

链路宽度。 SATA III 链路的速率为 6 Gbit/s,扣除协议开销后,实际数据速率约为 550 MB/s。这是固定上限,与后端使用哪种闪存无关。4 条 PCIe 通道每秒可传输数 GB,因此链路不再是瓶颈。

延迟通常最容易造成误判。在队列深度为 1 时,也就是只有一个请求在执行,一个 SATA SSD 完成一次 4k 读取大约需要 100 到 150 微秒。NVMe 大约需要 80 到 100 微秒。两者都很快,单个请求的差异不会被任何实际运行的程序察觉。并发请求增加后,差异才会显现。队列深度,即同时执行的请求数,决定了两种介质的表现是相近还是差异显著。

网络块存储属于第三类,其工作机制不同。写入请求会通过网络发送到存储集群,只有集群持久保存数据后才会确认,因此其延迟以毫秒而不是微秒计量。换来的优势是持久性:卷的生命周期不受所挂载主机影响,并且可以创建快照和调整大小。

NVMe、SATA SSD 和网络存储的典型公开数据

ChartTypical published figures: 4k random read, queue depth 32
The data behind this chart
[
  {
    "disk": "Local NVMe SSD",
    "iops_4k_read": "184,000",
    "p99_latency_ms": 0.4,
    "seq_read_mbps": "3,400"
  },
  {
    "disk": "Local SATA SSD",
    "iops_4k_read": "90,000",
    "p99_latency_ms": 1.2,
    "seq_read_mbps": "550"
  },
  {
    "disk": "Network block storage",
    "iops_4k_read": "12,500",
    "p99_latency_ms": 6.5,
    "seq_read_mbps": "250"
  }
]

本地 NVMe 设备在队列深度为 32 时,通常标称可达到 184,000 次随机 4k 读取 IOPS(每秒输入/输出操作数)。对 SATA SSD 进行相同测试时,通常约为 90,000,原因是它受单个 AHCI 队列和 6 Gbit/s 链路限制。网络块存储通常受提供商限制,而不是受硬件限制;12,500 是常见的文档标称上限。

延迟也会以用户能感知的单位体现出相同差异。p99 读取延迟是指最慢的 1% 请求的延迟。本地 NVMe 约为 0.4 ms,SATA 约为 1.2 ms。将网络加入路径后,延迟会达到 6.5 ms,超过 NVMe 数据的 10 倍。

顺序读取的差距最大,但参考价值最低:3,400 MB/s 对比 550 MB/s。服务器上几乎没有任务会以满速从头到尾读取一个大文件。随机读取和延迟两列更能说明数据库、邮件队列或软件包管理器的实际行为。

这些数据的来源,以及您的数据为何会不同

3 行数据来自本地设备的厂商数据表,以及网络存储按卷记录的限制值。截至 2026 年 7 月,这些数据已取整。测试假设块大小为 4k、执行随机读取、队列深度为 32,并使用单个任务,这符合厂商通常发布的测试条件。您的 VPS 是共享主机上的来宾实例,因此在您的服务器上进行相同测试通常会得到更低的结果,而且不同运行之间也会有差异。应将这些数据理解为三类存储之间差异的特征,而不是必须达到的目标。

哪些工作负载会受到磁盘影响

一条规则可以解释所有情况:只有在等待磁盘时,工作负载才会受到磁盘影响。Linux 会将最近使用的文件数据保存在 RAM 的页缓存中,因此第二次读取文件时不会访问存储设备。如果工作集(即实际使用中的数据)能放入 RAM,第一次读取后,后续读取就会变成内存读取。写入则不同。应用使用 fsync() 刷新数据时,任何写入都必须先写入稳定存储,应用才能继续执行。

提交事务的工作负载。 PostgreSQL、MySQL 和 SQLite 会在提交时调用 fsync()fdatasync(),每次提交都要等待设备响应。因此,单个连接的提交速率由写入延迟决定,而不是由带宽决定。刷新耗时 0.2 ms 的设备,每秒允许的提交次数远高于耗时 5 ms 的设备;吞吐量再高也无法改变这一点。当刷新速度跟不上时,MySQL 会在错误日志中记录这一情况:

[Note] InnoDB: page_cleaner: 1000ms intended loop took 4589ms. The settings might not be optimal.

PostgreSQL 会在检查点日志行中报告这一情况。其中,较大的 sync= 值表示刷新操作本身较慢:

LOG:  checkpoint complete: wrote 8192 buffers (25.0%); write=27.694 s, sync=11.207 s, total=39.001 s

操作大量小文件的工作负载。 每个文件都涉及元数据操作,而一次大型顺序读取不需要这些操作。npm install、大型仓库中的 git clone、解包容器镜像、Maildir 邮件存储,以及遍历大型目录树的备份任务,都会将大量时间花在小规模随机访问上。VPS 上的 restic 备份任务 会读取并计算此前未见过的每个文件的哈希值,因此,包含 1000000 个文件的备份,其实际耗时与随机读取延迟密切相关。du -sh 也是如此,它只读取元数据。

超出 RAM 容量的数据库也属于这一类。当索引不再能放入页缓存时,每次查找都会变成随机读取,磁盘也会重新处于关键路径上。

哪些工作负载不会受磁盘影响

博客或小型企业网站。 页面较小。首次请求后,页面缓存可以容纳所有页面。此时瓶颈是页面渲染所需的 CPU 或资源文件所需的带宽。在低流量网站上,预热后的 Ubuntu 24.04 上的 LAMP 堆栈 几乎不执行磁盘 IO。

媒体流式传输。 一路 4K 流的速率为 40 Mbit/s,读取速度为 5 MB/s。10 路流的读取速度为 50 MB/s,即使网络块存储也能轻松处理。VPS 上的 Jellyfin 媒体服务器 受网络出口流量额度限制;进行转码时受 CPU 限制,而不是受存储介质限制。

本地模型推理。 在 VPS 上运行 Ollama 以自行托管 LLM 时,模型文件只读取一次,之后在 RAM 中运行。NVMe 可将加载 20 GB 模型的时间从几分钟缩短到几秒。但它不会改变每秒生成的 token 数量,因为该指标受内存带宽和 CPU 限制。

任何等待外部服务的工作负载。 如果一个 worker 每个任务花费 800 ms 等待 HTTP 请求,使用更快的磁盘也不会提高速度。

为什么管理程序与存储介质同样重要

您从不直接与设备通信。您实际使用的是管理程序提供的虚拟磁盘,通常通过 virtio 提供。该层的多个决策,其影响往往大于 NVMe 与 SATA 之间的差异。

您无法从客户机内部查看存储介质。 lsblk -d -o NAME,ROTA,SIZE,MODEL 显示 vda,但型号为空,因为 virtio 不会传递驱动器标识。cat /sys/block/vda/queue/rotational 报告的是管理程序公布的信息,因此其中的 0 不能证明存储介质是闪存。nvme list 来自 nvme-cli 软件包。在大多数 VPS 上,即使宿主机装满 NVMe 驱动器,它也通常不会列出任何设备,因为您的磁盘是 virtio 设备,而不是 NVMe 设备。标注为 NVMe 的方案通常描述的是宿主机所使用的存储介质。您的卷仍可能通过网络连接。

宿主机的缓存模式对结果的影响大于存储介质。 启用宿主机写回缓存后,客户机中的 fsync() 可能在宿主机将数据写入自身 RAM 后立即返回。这会产生任何物理设备都无法达到的基准测试结果。这也意味着宿主机崩溃时,数据库认为已安全写入的数据可能会丢失。使用缓存模式 none 时,结果更低,但更真实。

限制和突发额度。 许多提供商会按卷或方案限制 IOPS,许多网络卷还使用突发额度。突发额度是一组积分:积分未耗尽时,卷可以高速运行;积分耗尽后,速度会降至低得多的基线水平。其表现很容易识别。导入或恢复操作会快速运行几分钟,然后突然大幅变慢,并持续保持低速,而您的配置没有任何变化。原因是突发额度已用尽。

邻居虚拟机。 在共享宿主机上,磁盘延迟会随其他客户机的负载变化。这就是需要多次测量的原因。在早上运行相同测试,晚上再运行一次,然后比较结果差异。在繁忙的宿主机上,同一卷两次测试之间的差异,往往大于已发布的两种存储介质之间的差异。

如何测量 VPS 实际拥有的磁盘

安装标准 IO 基准测试工具 fio,然后执行测量。先注意以下三点。测试会创建文件,因此会占用磁盘空间,也会计入您付费购买的 IOPS 配额。每次运行时间应保持较短。不要对正在提供实时网络流量的卷使用最大队列深度运行测试,否则测试会与您自己的应用争用资源。

sudo apt update && sudo apt install -y fio ioping sysstat
cd /var/tmp

队列深度为 32 的随机读取测试,这是供应商通常提供的测试深度:

fio --name=randread --filename=fio.test --size=1G --bs=4k --rw=randread \
  --ioengine=libaio --direct=1 --iodepth=32 --numjobs=1 \
  --runtime=30 --time_based --group_reporting

需要关注的行以 read: 开头。

  read: IOPS=184k, BW=719MiB/s (754MB/s)(21.1GiB/30001msec)

--direct=1 会绕过 guest page cache,因此结果反映的是设备性能,而不是内存性能。省略该选项后,测量的会是内存性能,返回的数值可能是磁盘无法达到的。空间允许时,请使用 --size=4G 或更大的文件,因为 1G 文件可能完全位于主机的缓存中,从而使结果偏高。

队列深度为 1 时可以显示原始延迟,这是单线程进程实际感受到的延迟:

fio --name=lat --filename=fio.test --size=1G --bs=4k --rw=randread \
  --ioengine=libaio --direct=1 --iodepth=1 --runtime=30 --time_based

提交测试可预测数据库行为。它每次写入 4k,并在每次写入后调用 fdatasync(),因此报告的速率包含 flush 操作的耗时:

fio --name=commit --filename=fio.test --size=1G --bs=4k --rw=randwrite \
  --ioengine=psync --fdatasync=1 --runtime=30 --time_based
rm -f fio.test

该测试得到的 IOPS 数值接近单个数据库连接每秒能够提交的小事务数上限,因为提交操作会等待同一个 flush 完成。

如需在不使用 fio 的情况下快速采样:

ioping -c 20 .
--- . (ext4 /dev/vda1) ioping statistics ---
19 requests completed in 4.13 ms, 76 KiB read, 4.60 k iops, 17.9 MiB/s
min/avg/max/mdev = 174.2 us / 217.6 us / 386.1 us / 51.3 us

mdev 值表示平均偏差,其重要性不低于平均值。空闲服务器上如果偏差很大,说明存储后端由多个用户共享且当前繁忙。

如何解读结果

截至 2026 年 7 月,以下结果对于小型 VPS 来说是合理的:在队列深度为 32 时,4k 随机读取 IOPS 达到数万,且队列深度为 1 时的延迟低于约 0.3 ms,这通常说明使用的是本地闪存。队列深度为 1 时延迟达到数毫秒,则说明存在网络路径,无论套餐名称是什么。顺序读取速度接近 550 MB/s 后停止,这是 SATA 链路的典型特征。如果数值远高于任何单个设备的能力,则说明链路中存在缓存,几乎总是在主机上。

要查看当前工作负载对磁盘的影响:

iostat -x 1 3
vmstat 1 5
cat /proc/pressure/io

iostat -x 输出中,查看 r_awaitw_await,它们分别表示请求等待的平均毫秒数,以及 aqu-sz,即平均队列长度。虚拟磁盘应忽略 %util。它表示至少有一个请求处于等待状态的时间占比。对于可同时处理大量请求的设备,这一指标无法说明设备是否已饱和。因此,%util 为 100 且 r_await 为 0.2 ms,表示磁盘处于繁忙但健康的状态。在 vmstat 中,wa 列表示 CPU 时间中等待 IO 的百分比。如果内核中存在 /proc/pressure/io,其 some avg10= 值表示最近 10 秒内至少有一个任务因 IO 停滞的时间占比。这是判断存储是否为瓶颈的最直接指标。

磁盘受限的 VPS 表现

高负载平均值、空闲 CPU,以及 vmstat 中较大的 wa,表示进程正在等待磁盘。最明确的内核信号是 dmesg -T 中的这条消息:

INFO: task jbd2/vda1-8:194 blocked for more than 120 seconds.

这行消息出现的原因是某个内核线程等待存储设备响应超过两分钟,因此 hung task watchdog 记录了它。jbd2 是 ext4 日志线程,这表示整个文件系统都在等待,而不是某个行为异常的程序。在 VPS 上,这通常指向存储后端或已耗尽的 IOPS 配额。

应用程序的症状也符合这一模式。中位响应时间仍然可以接受,但最慢请求的尾延迟会明显增加,因为只有访问磁盘的请求受到影响。apt upgrade 会在 Unpacking 阶段停留数分钟,因为 dpkg 在写入时会执行 flush。大型仓库中的 git status 需要数秒。这些是元数据和 flush 操作的开销,因此增加带宽不会有帮助。

磁盘成为瓶颈时的处理方法

先购买 RAM,再购买 IOPS。 如果工作集能放入页缓存,读取就完全不会到达磁盘。内存翻倍通常比迁移到更快的存储类型更有效,而且通常成本更低。

在数据允许的情况下,减少 flush 次数。 在 PostgreSQL 中,synchronous_commit = off 允许提交在数据写入磁盘前返回。如果服务器宕机,最后几分之一秒内的事务可能会丢失。数据库不会损坏,因为预写日志仍会按顺序写入。对于分析副本,这种权衡是合适的;对于支付系统则不合适。MySQL 中的 innodb_flush_log_at_trx_commit = 2 也是相同的权衡。

批量处理小文件。 传输或备份一百万个小文件时,耗时主要由每个文件的固定开销决定。因此,在高延迟存储上,先归档再传输一个数据流,比逐个文件复制目录树更快。

确保精简卷上的 discard 正常工作。 在精简配置的存储上,后端只有在文件系统告知某个块已空闲后,才知道该块可以释放。如果卷从不执行 trim,写入性能会逐渐下降。Ubuntu 提供了一个每周运行的 timer:

systemctl status fstrim.timer
sudo fstrim -av

fstrim -av 会输出每个挂载点修剪的字节数。如果消息表示不支持 discard,说明虚拟磁盘未将 discard 传递给主机,因此无需修复任何问题。

不要调整 IO scheduler。 对于 virtio 磁盘,cat /sys/block/vda/queue/scheduler 通常已经显示 none,实际调度发生在主机上,而您无法访问主机。同样跳过 noatime:Ubuntu 默认使用 relatime 挂载,这已经避免了几乎所有 atime 写入。

选择方案

如果服务器上运行数据库、邮件服务器、CI runner 或依赖大量软件包的构建任务,请选择 NVMe。对于缓存型网站,或主要耗时在外部调用上的应用,不要为 NVMe 支付溢价。如果不确定,磁盘可能不是瓶颈,因为大多数小型 VPS 工作负载通常会先耗尽 RAM 或带宽。

从第一天开始测量,同时完成新 VPS 上的前十分钟,并将输出保存到文件中。基线数据可以帮助您之后证明主机变慢了,而不是代码变慢了。优先选择明确说明存储类型以及 IOPS 上限的提供商。如果方案标注为 NVMe,但 queue depth 1 的读取耗时为 4 ms,说明您使用的是配备 NVMe 的主机上的网络存储。这种产品可以销售,但与您购买的产品不同。

FAQ

在 VPS 上,NVMe 总是比 SATA SSD 快吗?

不一定。在队列深度为 1 时,两者的性能接近。4k 读取的延迟大约为 80 到 150 微秒,单线程程序无法区分两者。存在大量并发请求时,NVMe 才会体现优势。这是因为 AHCI 只有一个队列,队列深度为 32 个命令,而 NVMe 提供数千个更深的队列。在共享主机上,其他客户机产生的负载对延迟的影响可能大于存储介质本身。因此,请使用 fio 测量您自己的卷,不要只看套餐名称。

如何检查我的 VPS 是否确实使用 NVMe?

无法直接检查,因为 virtio 会隐藏物理设备。lsblk 显示 vda,但不提供型号字符串;nvme list 不返回任何内容;/sys/block/vda/queue/rotational 只报告 hypervisor 对外公布的信息。请改为测量实际性能。队列深度为 1 的随机 4k 读取延迟低于约 0.3 ms,表示使用本地闪存。延迟达到数毫秒,表示链路中存在网络跳转。顺序读取速度接近 550 MB/s 后停止,表示使用 SATA 链路。

NVMe 会让我的网站加载更快吗?

通常不会。首次请求之后,Linux 会从 RAM 中的页面缓存提供文件,磁盘因此处于空闲状态。小型 VPS 的页面速度通常受应用 CPU 时间和带宽限制。如果网站在每次请求时都写入数据,磁盘就会重新进入关键路径。例如,数据库驱动的购物车频繁提交事务时,每次提交都必须等待 flush 完成。

VPS 的 fio 测试结果达到什么水平才算好?

截至 2026 年 7 月,使用本地闪存的小型 VPS 在队列深度为 32 时,通常可达到每秒数万次 4k 随机读取 IOPS;队列深度为 1 时,延迟低于 0.3 ms。网络块存储通常只能达到每秒数千次 IOPS,延迟为数毫秒。请在不同时间运行 3 次测试。多次运行结果差异较大,比平均值更能说明问题,因为这表明主机上其他客户机对您的影响有多大。

应该将数据库放在网络块存储上吗?

可以,许多托管服务也这样做,但提交路径会因此产生额外开销。每次 flush 都要经过网络,因此单个连接每秒提交的小型事务数量会少于使用本地闪存时的数量。作为交换,您可以获得即使主机故障也能保留的数据持久性。如果为写入密集型数据库选择网络存储,请将多个操作合并到更大的事务中,使更少的 flush 携带更多行。

#nvme#ssd#存储#性能#benchmarking