香港服务器960G NVMe SSD随机IOPS达到百万级后,站点读写如何验收?
针对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 | 中位延迟 | 普通请求体验 |
| p95 | 95%请求的延迟边界 | 大多数请求是否稳定 |
| p99 | 99%请求的延迟边界 | 尾部慢请求是否可接受 |
| 错误率 | 请求或 I/O失败比例 | 是否出现超时、5xx或数据错误 |
await | 设备层等待时间 | 磁盘响应是否出现排队 |
aqu-sz | 平均队列长度 | 是否持续积压 |
%iowait | CPU等待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. 裸盘未达到百万级
先不要立即判定硬盘不达标,应逐项核对:
- 块大小是否确实为 4 KiB;
--direct=1是否生效;iodepth和numjobs是否达到预期;- 测试文件是否位于目标 NVMe 挂载点;
- 测试时是否存在备份、日志、更新或其他 I/O;
- CPU是否已经满载,导致压测线程无法发起足够请求;
- 设备温度和健康信息是否出现异常;
- 测试结果是否在长时间运行后明显下降。
如果 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 和错误率。
最终的签收判断应分成两层:

- 存储基准通过:在明确的块大小、队列深度、读写比例和测试时长下,原始 NVMe 结果达到约定目标。
- 站点读写通过:真实读取和写入请求的吞吐、p95/p99、错误率、持久化确认及回读一致性均达到业务要求。
只有两层都通过,才能确认这台 960G NVMe SSD香港服务器的随机 I/O 性能已经真正满足站点读写场景。验收完成后,应保留测试命令、环境信息、原始结果和复测条件,便于后续扩容、迁移或性能变化时进行同口径对比。