上一篇 下一篇 分享链接 返回 返回顶部

香港服务器960G NVMe SSD随机IOPS达到百万级后,站点读写如何验收?

发布人:Minchunlin 发布时间:2026-10-04 23:20 阅读量:4

针对960G NVMe SSD香港服务器,站点读写验收不能只看“随机IOPS超过100万”这一行结果。正确做法是先固定测试条件,用 fio 验证存储层,再用与实际站点一致的读请求、写请求和持久化方式验证应用层,最后同时核对 IOPS、吞吐、延迟分位数、错误率、CPU 负载和磁盘队列。

只有在测试块大小、读写比例、并发深度、测试时长和 fsync 行为都明确的前提下,“百万级随机IOPS”才有比较意义。若裸盘达到百万级,但站点接口的 p99 延迟、写入成功率或持久化结果不达标,只能说明存储基准通过,不能判定站点读写验收通过。

一、先固定验收口径

1. 明确“百万级”对应的测试条件

IOPS 是每秒完成的 I/O 操作次数,并不是一个脱离条件的固定性能值。以下参数发生变化,结果就不能直接比较:

  • 块大小,例如 4 KiB、8 KiB、16 KiB;
  • 读写比例,例如 100% 随机读、70% 读加 30% 写;
  • 并发队列深度,即 iodepth;
  • 并发任务数,即 numjobs;
  • 是否使用直接 I/O,即 direct=1;
  • 写入是否要求落盘,即 fsync=1 或应用自身的提交机制;
  • 测试文件大小、文件系统、挂载参数和测试持续时间。

如果验收目标写的是“4 KiB 随机读达到百万级 IOPS”,至少应记录为:

4 KiB、100%随机读、指定队列深度和并发任务数、直接 I/O、预热后持续测试若干秒,聚合 IOPS 不低于目标值。

如果没有写明这些条件,“百万级”就无法判断是低队列深度下的真实站点能力,还是高并发压测下的峰值结果。

2. 区分容量、吞吐和 IOPS

960G 是容量标识,不等于一定具备百万级随机读写能力。硬盘厂商使用十进制容量时,960G 通常表示约 960,000,000,000 字节,系统按二进制显示时约为 894 GiB。系统中看到的可用容量还会受到文件系统、预留空间和已有数据影响。

IOPS 与吞吐量的关系可以用下面的方式理解:

吞吐量 = IOPS × 单次 I/O 数据量

例如,4 KiB 随机 I/O 达到 1,000,000 IOPS 时:

  • 每秒数据量 = 1,000,000 × 4,096 字节;
  • 结果为 4,096,000,000 字节/秒;
  • 按十进制换算约为 4.096 GB/s;
  • 按二进制换算约为 3,906 MiB/s。

因此,看到“百万级 IOPS”时,还要检查输出中的 BW 是否与块大小和 IOPS相符。4 KiB、100万 IOPS与16 KiB、100万 IOPS代表的吞吐压力并不相同。

3. 建议提前形成验收矩阵

验收层级典型测试条件主要观察指标通过依据
存储基准4 KiB随机读,固定队列深度和并发任务IOPS、BW、p95/p99延迟达到约定目标,结果稳定
混合读写4 KiB,明确读写比例读 IOPS、写 IOPS、总 IOPS、延迟达到混合负载目标
持久化写入随机写,启用与应用一致的同步机制写 IOPS、fsync延迟、错误率写入确认与落盘要求一致
站点读取实际页面、静态文件或读取接口RPS、p95/p99、错误率、磁盘读请求页面或接口目标达标
站点写入测试账号、固定数据量、真实提交路径成功率、提交延迟、磁盘写请求数据写入、提交和回读均正常

这张表中的目标值应以业务需求或采购约定为准。没有统一适用于所有站点的 p99、写入 IOPS 或并发数,不能用某一个参考数字替代真实验收标准。

二、验收前检查服务器状态

1. 确认测试目录确实位于目标 NVMe 挂载点

不要直接把测试命令指向 /dev/nvme0n1 等裸设备。裸设备测试可能覆盖分区或文件系统数据,属于高风险操作。站点验收应优先使用目标文件系统中的专用测试目录。

先记录服务器、内核、挂载点和空间情况:

date -Is
hostname
uname -a
findmnt -T /var/www
lsblk -o NAME,TYPE,SIZE,FSTYPE,MOUNTPOINTS,MODEL
df -hT /var/www

将 /var/www 替换为站点实际使用的目录。若站点文件位于独立数据盘,还应确认网站上传目录、缓存目录或数据库数据目录是否与测试目录处于同一挂载点。

可以进一步查看 NVMe 设备信息:

command -v nvme && nvme list
command -v nvme && sudo nvme smart-log /dev/nvme0

如果系统没有安装 nvme-cli,不要为了验收临时改变生产环境。记录已有信息即可,或在维护窗口内由管理员按既定流程补充工具。smart-log 是读取操作,但设备路径仍需根据 lsblk 输出确认,不能机械使用 /dev/nvme0。

重点留存以下信息:

  • NVMe 设备名称和实际挂载点;
  • 文件系统类型;
  • 已用空间和可用空间;
  • 挂载参数;
  • 内核版本和 fio 版本;
  • 测试时是否有备份、日志轮转、更新任务或其他大规模 I/O。

2. 确定测试范围并保护站点数据

原始 fio 测试会产生大量读写。预填充测试文件还会占用目录空间,并增加 SSD 写入量。因此执行前应满足以下条件:

  • 优先使用测试站点、业务副本或维护窗口;
  • 站点数据和配置已经完成备份;
  • 测试目录是专门创建、可以明确识别的路径;
  • 可用空间足以容纳测试文件,并为正常业务保留余量;
  • 不把测试文件放入上传目录、数据库数据目录或用户可访问目录;
  • 不在生产高峰期运行高队列深度测试。

例如,下面的路径仅作为专用测试目录示例:

mkdir -p /srv/fio-acceptance
df -hT /srv/fio-acceptance

后续测试会在这个目录内创建约 64G 的测试文件。这里的 64G 不是固定要求,而是一个便于观察的示例规模。测试文件过小,可能受到缓存和文件系统元数据影响;测试文件过大,则会增加空间占用、写放大和测试时间。

测试结束后不要立即删除证据。先归档测试输出,确认路径确实是专用测试目录,再由管理员按备份和变更流程清理。不要使用模糊的递归删除命令处理测试目录,否则可能误删站点文件;如果误指定了业务路径,应立即停止测试并按照备份方案恢复。

3. 记录测试期间的系统指标

fio 结果只能说明测试进程观察到的 I/O 表现,还需要同步记录设备队列、CPU 等待和系统负载:

iostat -xm 1

如果系统没有 iostat,不要随意安装或升级生产软件包,可使用现有监控系统;在测试环境中也可以按发行版既定方式安装 sysstat 后再测试。

重点观察:

  • r/s 和 w/s:设备每秒读写请求数;
  • await:设备层 I/O 平均等待时间,单位通常为毫秒;
  • aqu-sz:平均请求队列长度;
  • %util:设备忙碌程度;
  • CPU 的 %iowait:CPU 等待 I/O 的时间比例;
  • 测试期间是否出现延迟逐步升高或吞吐逐步下降。

await 是设备层指标,不等于网页接口的响应时间。网页 p99 很高而设备 await 正常时,问题可能位于应用执行、锁等待、网络往返或同步提交过程。

三、先完成存储层基准测试

1. 预填充测试文件

如果测试目录中没有可读数据,应先在专用目录内生成测试文件。下面示例使用 8 个任务、每个任务 8G,总量约 64G:

fio --name=prepare \
  --directory=/srv/fio-acceptance \
  --rw=write \
  --bs=1M \
  --size=8G \
  --numjobs=8 \
  --ioengine=libaio \
  --direct=1 \
  --iodepth=32 \
  --group_reporting

该步骤的结果不作为随机读写验收结果,因为它只是准备测试数据。执行时要注意:

  • --size=8G 是每个任务的文件大小,8 个任务合计约 64G;
  • 测试目录必须是确认过的专用目录;
  • 预填充会产生真实写入负载;
  • 如果 libaio 不可用,应先检查 fio --enghelp 和系统支持情况,不要在不同 I/O 引擎之间直接比较结果;
  • 测试过程中如果站点出现明显延迟、错误或空间告警,应立即停止并记录当时状态。

2. 测试 4 KiB 随机读

百万级随机 IOPS通常需要较高并发深度。下面是一个参考测试配置:

fio --name=randread-4k \
  --directory=/srv/fio-acceptance \
  --rw=randread \
  --bs=4k \
  --size=8G \
  --numjobs=8 \
  --ioengine=libaio \
  --direct=1 \
  --iodepth=64 \
  --runtime=60 \
  --ramp_time=15 \
  --time_based \
  --group_reporting \
  --output=/srv/fio-acceptance/randread-4k.txt

这个配置的聚合队列深度大约为 8×64,但它不等同于网站真实并发数。命令中的 --ramp_time=15 用于预热,正式观察应以之后的 60 秒为准。

输出中重点查看:

  • IOPS:是否达到约定的百万级目标;
  • BW:是否与 4 KiB 块大小和 IOPS大致匹配;
  • clat:完成延迟;
  • p95、p99、p99.9:尾部延迟;
  • error:是否有 I/O 错误;
  • IO depths:实际达到的队列深度是否与配置接近。

一个仅用于解释格式的示例结果可能类似:

read: IOPS=1.01M, BW=3.86GiB/s
clat percentiles:
  |  50.00th=120us
  |  95.00th=310us
  |  99.00th=850us
  |  99.90th=2.10ms

这表示该组测试条件下的聚合随机读结果约为 101万 IOPS,不代表当前服务器的实际结果,也不能直接推导出站点每秒能处理 101万个页面请求。网页请求通常还要经过 Web 服务、应用代码、模板、缓存和网络响应过程。

3. 测试混合随机读写

站点很少只有读没有写。访问日志、会话、上传、缓存更新和内容修改都会带来写请求,因此需要单独测试混合负载:

fio --name=randrw-4k-70read \
  --directory=/srv/fio-acceptance \
  --rw=randrw \
  --rwmixread=70 \
  --bs=4k \
  --size=8G \
  --numjobs=8 \
  --ioengine=libaio \
  --direct=1 \
  --iodepth=32 \
  --runtime=60 \
  --ramp_time=15 \
  --time_based \
  --group_reporting \
  --output=/srv/fio-acceptance/randrw-4k-70read.txt

这里的 70 表示读操作约占 70%,写操作约占 30%。如果实际站点是 90%读、10%写,或者写入比例更高,应按业务画像修改,不能用 70/30 的结果替代实际场景。

混合测试中常见的判断方式是:

  • 读 IOPS达标,但写 IOPS明显降低:说明写入路径或写放大影响较大;
  • 总 IOPS较高,但 p99延迟明显上升:说明平均吞吐不错,尾部请求可能已经不适合站点交互;
  • 读写比例改变后结果差异很大:应以站点实际比例为准;
  • 测试初期较高、后期持续下降:需要检查温度、缓存、后台回收和长时间稳定性。

4. 单独测试需要落盘确认的写入

普通 randwrite 可能主要反映数据进入 I/O 队列的速度,而站点订单、内容保存或其他需要持久化确认的操作,往往要等待同步提交。可以使用专用测试目录进行参考测试:

fio --name=randwrite-4k-sync \
  --directory=/srv/fio-acceptance \
  --rw=randwrite \
  --bs=4k \
  --size=8G \
  --numjobs=8 \
  --ioengine=libaio \
  --direct=1 \
  --iodepth=1 \
  --fsync=1 \
  --runtime=60 \
  --ramp_time=15 \
  --time_based \
  --group_reporting \
  --output=/srv/fio-acceptance/randwrite-4k-sync.txt

这里的 --fsync=1 会显著改变写入行为,结果不能与未启用同步机制的随机写直接比较。--iodepth=1 也只是示例,目的是让每个任务以更接近同步提交的方式运行;如果应用使用批量提交、事务日志或其他机制,应在站点层按实际行为复测。

不要用“随机读百万级”推断“同步写也百万级”。读和写是两条不同的验收项,普通写入和持久化写入也应分开记录。

四、把结果落到真实站点读写

1. 先定义站点测试对象

站点层测试应尽量接近真实请求,不宜只访问一个会被缓存长期命中的首页。可以在测试站点或维护窗口中准备:

四、把结果落到真实站点读写配图

  • 一组大小不同的静态文件;
  • 一个会读取文件或内容数据的页面;
  • 一个固定大小的上传或内容保存请求;
  • 一个写入后可以回读的测试记录;
  • 独立的测试账号和测试数据;
  • 明确的清理方式,不直接操作生产数据库表或业务文件。

读测试要记录缓存状态。可以分别做“冷缓存”和“热缓存”两组,但必须标明测试条件。热缓存更能反映缓存命中后的接口能力,冷缓存才更容易观察存储读取压力。两者不能混在一组结果中。

写测试应使用应用原本的提交路径。如果业务要求用户点击保存后才算成功,就要以接口返回成功和数据回读成功为准,而不是只看服务器端 write() 是否返回。若业务要求提交后立即持久化,还应把同步提交的等待时间纳入站点 p99。

2. 读取接口的基础检查

可以先用单请求确认状态码和响应时间:

curl -sS -o /dev/null \
  -w 'code=%{http_code} total=%{time_total}s size=%{size_download}B\n' \
  'https://test.example.com/test-read'

这个命令只适合做连通性和单请求基线,不适合替代并发测试。确认测试域名、证书、路径和测试数据无误后,再使用已经安装并经过审批的压测工具,例如:

wrk -t4 -c64 -d60s --latency \
  'https://test.example.com/test-read'

参数含义如下:

  • -t4:4 个压测线程;
  • -c64:保持 64 个并发连接;
  • -d60s:持续 60 秒;
  • --latency:输出延迟分布。

并发数应从低到高逐级增加,例如先做低并发基线,再接近目标并发,最后进行峰值验证。不要一开始就用高并发冲击生产站点。压测客户端位置、协议、连接复用、TLS状态和请求路径都应记录,因为这些因素会影响网页请求延迟,但不会改变本地 fio 的磁盘结果。

3. 写入接口必须验证“成功”和“可回读”

没有统一的写入接口命令可以适用于所有站点。上传文件、保存内容、更新缓存和写入日志的语义不同,因此写测试应按照站点原有接口执行。

每次写请求至少保留以下结果:

  • HTTP 状态码或应用层业务码;
  • 应用返回的保存成功标志;
  • 服务端实际写入的数据大小;
  • 从读接口回读后的内容校验;
  • 提交耗时和等待落盘耗时;
  • 超时、重试、重复写入和数据不一致数量。

测试数据应使用固定大小,例如 4 KiB、64 KiB、1 MiB 等,并记录每类数据的比例。写入后回读可以采用哈希或固定标识校验,但不要在生产数据上执行不受控的清理和覆盖操作。

如果站点写请求返回成功,但回读不到数据,不能仅凭磁盘 w/s 达标判定通过。这类情况可能是异步队列、应用缓存、权限、路径配置或数据提交流程的问题。

五、读写结果应该看哪些指标

1. IOPS不是站点唯一通过条件

站点验收至少需要同时观察以下指标:

指标含义验收关注点
IOPS每秒完成的存储操作数是否达到约定负载下的目标
BW每秒传输数据量是否与块大小和IOPS匹配
p50中位延迟普通请求体验
p9595%请求的延迟边界大多数请求是否稳定
p9999%请求的延迟边界尾部慢请求是否可接受
错误率请求或 I/O失败比例是否出现超时、5xx或数据错误
await设备层等待时间磁盘响应是否出现排队
aqu-sz平均队列长度是否持续积压
%iowaitCPU等待I/O比例存储是否成为系统瓶颈
回读一致性写入后是否能读到正确数据持久化链路是否完整

例如,原始随机读结果达到 1.01M IOPS,但站点读取只有 18,000 RPS、p99 为 80ms,不能简单说“站点达到百万级”。原始测试与站点请求不是同一个统计对象:一个 I/O 操作可能只是 4 KiB 读请求,而一个页面请求可能触发多个文件、模板或数据读取。

2. 示例结果如何解释

下面是一组用于说明判断方法的示例数据,不代表某台当前服务器的实测结果:

五、读写结果应该看哪些指标配图

测试项目示例结果判断
4 KiB随机读1.01M IOPS,p99 0.85ms在该队列和并发条件下,存储读基准达到百万级
4 KiB 70/30混合总计 620k IOPS,p99 1.8ms不能用随机读结果替代混合读写能力
同步随机写8.2k IOPS,p99 4.6ms说明持久化写入成本明显高于普通随机读
站点读取18k RPS,p99 35ms,错误率 0需要与站点目标比较,不能直接与裸盘 IOPS比较
站点写入4.8k次/秒,p99 28ms,回读一致若业务目标低于此值,可进入复核阶段

这组数据的核心含义是:读基准达到百万级,并不意味着写入也达到百万级;站点每秒请求数也不等于磁盘 IOPS。最终是否通过,应以事先确定的站点目标、尾延迟和数据正确性为准。

六、常见结果分支与下一步判断

1. 裸盘未达到百万级

先不要立即判定硬盘不达标,应逐项核对:

  1. 块大小是否确实为 4 KiB;
  2. --direct=1 是否生效;
  3. iodepth 和 numjobs 是否达到预期;
  4. 测试文件是否位于目标 NVMe 挂载点;
  5. 测试时是否存在备份、日志、更新或其他 I/O;
  6. CPU是否已经满载,导致压测线程无法发起足够请求;
  7. 设备温度和健康信息是否出现异常;
  8. 测试结果是否在长时间运行后明显下降。

如果 IO depths 显示实际队列深度远低于配置值,继续提高 iodepth 可能没有意义,应先检查 I/O 引擎、文件系统和 CPU状态。

2. 裸盘达到百万级,站点读取却很慢

这种情况通常说明瓶颈不在“存储峰值 IOPS”本身。应对照站点压测期间的指标:

  • CPU使用率很高:应用计算或压测线程成为瓶颈;
  • 磁盘 r/s 很低而页面延迟很高:请求可能卡在应用处理、网络或锁等待;
  • 磁盘 await 明显升高:站点实际请求可能使用了不同块大小或不同访问模式;
  • 热缓存很快、冷缓存很慢:缓存命中状态对结果影响较大;
  • 站点读取请求触发多个小文件或数据查询:一次页面请求可能包含多个 I/O;
  • p50正常但 p99很高:少量慢请求、后台任务或队列积压需要单独留证。

此时应重新建立与站点一致的读取场景,而不是继续用更高队列深度重复 fio。

3. 随机读达标,写入或同步写不达标

这是常见结果,并不必然表示测试错误。写入通常还会受到以下因素影响:

  • 读写混合比例;
  • 文件系统元数据更新;
  • 写入放大;
  • 应用是否等待 fsync;
  • 业务事务提交;
  • 站点是否同时生成日志、缩略图或缓存文件。

应分别报告普通写入、混合写入和同步写入结果。若业务要求“用户看到保存成功后数据必须具备持久性”,就不能用未启用同步机制的 randwrite 结果作为验收依据。

4. 首次结果很好,持续测试后下降

这类现象应记录完整时间序列,而不是只截取峰值。常见原因包括:

  • 设备温度升高后触发性能限制;
  • 测试文件过小,初期受缓存影响;
  • 长时间写入触发后台回收;
  • 其他任务在中途开始运行;
  • 可用空间或文件系统状态变化。

可以延长预热和正式测试时间,在相同条件下进行三次复测,并保留每秒或每个时间窗口的 IOPS、延迟和设备状态。

七、把异常和结果完整留证

验收争议往往不是因为没有跑测试,而是因为缺少可复核的上下文。建议每次测试至少保存:

  • 测试开始和结束时间;
  • 服务器主机名、内核和 fio 版本;
  • 设备、分区、文件系统和挂载点;
  • 测试目录、文件总量和可用空间;
  • 完整 fio 命令;
  • 原始终端输出;
  • iostat 输出;
  • 站点压测工具、线程数、连接数和持续时间;
  • 请求路径、数据大小和读写比例;
  • p50、p95、p99、错误率和回读校验结果;
  • 测试期间的 CPU、内存、磁盘温度和后台任务状态。

例如,可以先记录版本和环境:

date -Is | tee /srv/fio-acceptance/environment.txt
fio --version | tee -a /srv/fio-acceptance/environment.txt
uname -a | tee -a /srv/fio-acceptance/environment.txt
findmnt -T /srv/fio-acceptance | tee -a /srv/fio-acceptance/environment.txt
df -hT /srv/fio-acceptance | tee -a /srv/fio-acceptance/environment.txt

执行 fio 时保留原始输出:

fio --name=randread-4k \
  --directory=/srv/fio-acceptance \
  --rw=randread \
  --bs=4k \
  --size=8G \
  --numjobs=8 \
  --ioengine=libaio \
  --direct=1 \
  --iodepth=64 \
  --runtime=60 \
  --ramp_time=15 \
  --time_based \
  --group_reporting \
  | tee /srv/fio-acceptance/randread-4k-run1.txt

如果同时运行 iostat,应在单独终端启动,并将开始时间与 fio 对齐:

iostat -xm 1 75 | tee /srv/fio-acceptance/iostat-randread-run1.txt

日志中如果包含域名、账号、请求参数或用户数据,应先脱敏再交付。原始文件可以按照内部权限保存,公开或跨团队流转的副本不应包含凭据和个人信息。

八、按相同条件复测后再签收

单次峰值不能作为稳定性结论。复测时应保持以下条件不变:

  • 同一台服务器和同一块 NVMe;
  • 同一挂载点和文件系统;
  • 同一测试文件规模;
  • 同一块大小、读写比例、iodepth 和 numjobs;
  • 同一 direct、fsync 和 I/O 引擎设置;
  • 同一预热时间和正式测试时长;
  • 同一站点版本、数据集和缓存状态;
  • 同一压测客户端、连接数和请求路径;
  • 同一测试时间窗口或等价的业务负载条件。

建议至少完成三轮结果,并分别保留原始输出。验收记录可以同时填写:

  • 三轮 IOPS 的中位数;
  • 三轮结果的最大值和最小值;
  • p95、p99 的最大值;
  • 站点错误率和写后回读一致性;
  • 是否出现温度、队列或 CPU异常。

如果采购或项目协议已经约定了允许波动范围,应按协议执行。没有约定时,不要事后自行把某一轮峰值当成标准,也不要仅凭平均值忽略 p99 和错误率。

最终的签收判断应分成两层:

八、按相同条件复测后再签收配图

  1. 存储基准通过:在明确的块大小、队列深度、读写比例和测试时长下,原始 NVMe 结果达到约定目标。
  2. 站点读写通过:真实读取和写入请求的吞吐、p95/p99、错误率、持久化确认及回读一致性均达到业务要求。

只有两层都通过,才能确认这台 960G NVMe SSD香港服务器的随机 I/O 性能已经真正满足站点读写场景。验收完成后,应保留测试命令、环境信息、原始结果和复测条件,便于后续扩容、迁移或性能变化时进行同口径对比。

目录结构
全文