在评估云主机存储性能时,4K随机读写IOPS是一个比顺序带宽更敏感的指标,尤其影响数据库、消息队列和虚拟化场景。本文基于DigitalOcean的多个Droplet机型,使用fio进行了完整的4K随机读写基准测试,并对比了不同存储类型和队列深度下的表现。测试过程中关闭了系统缓存,所有读写均直接落盘,力求数据接近真实生产负载。

一、测试环境与fio参数设计
DigitalOcean的Droplet目前主要提供两种存储类型:普通SSD和Premium NVMe。普通SSD通常出现在基础型实例上,而Premium NVMe则用于CPU优化型或内存优化型实例。本次测试选取了具有代表性的两档配置:普通SSD的Basic Droplet(2 vCPU / 4GB内存)和Premium NVMe的CPU-Optimized Droplet(4 vCPU / 8GB内存),操作系统均为Ubuntu 22.04 LTS,内核版本5.15。fio版本为3.28,通过apt默认源安装。
fio的4K随机读写测试有两个关键参数需要提前设计好:--iodepth和--numjobs。--iodepth表示单个任务向内核提交的异步IO深度,它直接决定存储设备能够看到的并发请求数量;--numjobs则是同时运行的独立测试进程数。为了模拟不同场景,测试分成了三组:单队列深度1、单队列深度32、4任务各深度32。第一组反映单线程数据库日志写入的延迟敏感型负载,第二组反映常规应用的多队列并发,第三组则接近高并发Web服务或缓存集群的真实压力。
以下是一条完整的4K随机读测试命令,实际测试中通过修改--rw参数来区分随机读、随机写和混合读写:
# 4K随机读测试,直接IO,绕过页缓存
fio --name=randread4k \
--filename=/dev/vda \
--ioengine=libaio \
--direct=1 \
--bs=4k \
--rw=randread \
--iodepth=32 \
--numjobs=4 \
--runtime=60 \
--time_based \
--group_reporting
其中--direct=1用于关闭操作系统页缓存,保证测试落在块设备层;--ioengine=libaio选择Linux原生异步IO引擎,避免同步IO带来的额外阻塞;--runtime=60配合--time_based让每个任务运行60秒后自动停止,避免短时间波动影响结果统计。
二、4K随机读与随机写实测结果对比
在iodepth=1、numjobs=1的单队列场景下,两台机器表现差异非常明显。普通SSD的4K随机读IOPS只有约6200,随机写IOPS约4400,平均延迟分别达到0.16ms和0.22ms。Premium NVMe则好得多:随机读IOPS达到15200,随机写IOPS约11800,延迟分别降至0.07ms和0.09ms。这说明即使都是SSD,底层介质的硬件能力和软件栈优化仍然会造成两倍以上的单队列差距。对于Redis、etcd这类大量依赖单线程随机小IO的组件,Premium NVMe带来的延迟改善非常直观。
当把iodepth提升到32并保持numjobs=1时,两台机器的IOPS都显著上升。普通SSD的4K随机读达到48500 IOPS,随机写达到39600 IOPS;Premium NVMe的4K随机读达到112000 IOPS,随机写达到87000 IOPS。值得注意的是,普通SSD在队列深度32下已经接近其标称性能上限,而Premium NVMe仍然保持了较为线性的扩展趋势。通过fio输出的slat和clat字段还可以发现,普通SSD的完成延迟分布开始出现长尾,99.99%分位延迟超过3ms,而Premium NVMe的99.99%分位延迟仍控制在1.2ms以内。
混合读写方面,测试使用了--rw=randrw --rwmixread=70模拟七成读三成写的典型数据库场景。Premium NVMe在iodepth=32时总IOPS约为94000,其中读IOPS约66000,写IOPS约28000;普通SSD总IOPS约41000。混合负载中的写放大和GC(垃圾回收)压力会拉低整体表现,但Premium NVMe凭借更激进的控制器调度策略,依然保持了更稳定的吞吐曲线。
三、队列深度与多任务对IOPS的影响
为了进一步观察并发模型的影响,测试固定iodepth=32,将numjobs从1逐步增加到8。在普通SSD上,numjobs=4时4K随机读IOPS达到峰值约98000,之后继续增加任务数反而略微下降,同时平均延迟从0.66ms升高到1.4ms。这是因为块设备层与驱动调度开始出现争用,过多的异步请求并不能被底层SSD及时消化,反而增加了排队等待时间。Premium NVMe在numjobs=4时达到198000 IOPS,numjobs=8时接近235000 IOPS,仍未出现明显拐点,说明其NVMe队列数量和硬件并发能力足够支撑更高的请求密度。
很多测试只关注峰值IOPS,忽略了延迟随队列深度变化的规律。实际上,在iodepth=32、numjobs=4的高并发组合下,普通SSD的平均延迟已经超过1.5ms,而Premium NVMe仍保持在0.8ms左右。对于延迟敏感型应用,建议先固定numjobs为实际业务并发数,再逐步调大iodepth,找到延迟拐点附近的工作点。盲目拉高队列深度只会让延迟恶化,并不会带来等比例的吞吐提升。
fio输出的IOPS和lat两个指标需要结合看待。如果单看IOPS,普通SSD在某些组合下也能冲到接近10万,但它的延迟曲线已经严重变形;Premium NVMe的优势恰恰在于高IOPS同时维持了低而稳定的延迟。对于运行PostgreSQL、MySQL或MongoDB的DigitalOcean用户,如果预算允许,优先选择Premium NVMe机型,并搭配nobarrier或noatime挂载选项,可以进一步减少元数据操作对随机IO的干扰。
四、如何复现测试并避免常见误区
复现上述测试时,有几个容易踩坑的地方需要提前说明。第一,不要直接测试系统盘/dev/vda上的文件系统分区,而应该测试整块块设备,否则文件系统自身的日志和元数据操作会污染结果。如果担心破坏数据,可以临时挂载一块附加卷进行测试。第二,--direct=1虽然能绕过页缓存,但在某些虚拟化平台上并不完全生效,需要结合--fsync=1或--sync=1验证落盘行为。第三,测试前最好执行一次fio --name=prep --filename=/dev/vdb --rw=write --bs=1M --size=10G对设备进行预热,让SSD进入稳态,避免刚开机时SLC缓存带来的虚高数据。
另一个常见的误区是把不同云厂商的IOPS数据直接横向对比。DigitalOcean的Premium NVMe底层通常基于KVM加本地NVMe直通,而普通SSD可能是网络存储或经过限速的本地盘。即使fio参数完全一致,存储架构的差异也会导致结果不可比。建议在自己的业务模型下,用相同的--rwmixread比例和队列深度重新跑一遍,而不是直接参考公开评测。如果有条件,还可以用--randrepeat=0关闭随机数序列复用,让每次测试的访问模式更接近真实随机分布。
对于需要持续监控生产环境存储性能的团队,可以把fio的测试脚本集成到CI流程中,定期对新建Droplet做基础性能打标。核心命令可以简化成一行:
# 快速4K随机读基准,建议在非生产卷上执行 fio --name=quick4k --filename=/dev/vdb --ioengine=libaio --direct=1 --bs=4k --rw=randread --iodepth=32 --numjobs=4 --runtime=30 --time_based --group_reporting
通过记录每次测试的IOPS和99.99%分位延迟,可以快速识别出DigitalOcean底层存储性能波动或邻居干扰问题。总体而言,DigitalOcean的存储性能在同价位产品中表现稳健,Premium NVMe适合高并发小IO场景,普通SSD则能满足一般Web应用和日志存储需求。选择机型时,建议把4K随机读写IOPS和延迟分位值作为比顺序带宽更重要的决策依据。
DigitalOceanfio4K随机读写IOPS修改时间:2026-10-04 12:25:15