☰
Linux磁盘读写测试全攻略:dd、fio与实战避坑指南
2026/10/21 6:01:58 网站建设 项目流程

最近帮客户排查一台数据库服务器性能问题时,发现了一个很有意思的现象:系统负载不高,CPU和内存都很空闲,但业务就是慢。最后用工具一测磁盘读写能力,才发现瓶颈根本不在一开始的排查方向上。其实类似的情况我遇到过不少,很多人拿到Linux服务器第一反应就是"跑个测速看看",但磁盘读写测试这件事,看似简单,实际操作里全是细节——参数不同、块大小不同、缓存开没开、测的是裸设备还是文件系统,结果能差出好几倍甚至几十倍。这篇文章我就把Linux下测试磁盘读写能力这件事从头到尾聊透,包括常用工具怎么用、参数怎么选、结果怎么解读,以及这些年我在实际测试中踩过的坑。

如果你手头正好有台新机器要做存储性能验收,或者业务变慢想快速判断是不是磁盘拖了后腿,又或者想对比一下不同文件系统、不同RAID策略下的表现,这篇文章你应该能直接拿去参考。

1. 开始测试前,先想清楚这三个底层问题

很多测磁盘的人,上来就直接敲命令,敲完看个数字就完事了。但我建议你先花两分钟想清楚三个底层问题,否则你测出来的数字可能根本不能回答你想问的问题。

1.1 读写路径完全不同,测试姿势自然也不同

Linux下数据写入和读取,走的路径是完全不一样的。写入时,应用程序把数据丢给内核,内核先把数据放在页缓存(Page Cache)里,再由内核的IO调度器决定什么时候真正写进磁盘设备。而读取的时候,如果数据已经在页缓存里,那CPU直接读内存就把数据拿走了,根本不会碰磁盘;只有缓存里没有,才会真的去磁盘读。

这就引出一个很关键的点:测写速度时,如果你只满足了"数据被操作系统接收",那测的根本不是磁盘,而是内存带宽。测读速度时,如果你不把缓存里的数据先清掉,那测的依然是缓存。所以你看网上那些"dd一下测出每秒几个GB"的数据,多半都有这个问题。

1.2 Linux缓存机制让"裸测"结果失真

页缓存(Page Cache)是Linux内核为了加速文件读写设计的,本质上是把磁盘上最近读过的数据块留在内存里。它本身是个好东西,但放在磁盘性能测试场景里就是个"作弊器"——你以为在测磁盘,其实在测内存。

举个例子,我见过有人这么测写速度:

dd if=/dev/zero of=/tmp/speedtest bs=1M count=2048

这条命令在多数机器上跑出来可能每秒好几个GB,你看了很高兴,但实际上,/tmp/speedtest这个文件的大部分数据还在页缓存里泡着,根本没落盘。这时候你拔电源,文件大概率是坏的。正确的测法我们后面讲,这里你只需要记住:测试工具的结果不代表磁盘真实速度,必须主动绕开缓存才能测到真实水平。

1.3 顺序大IO和随机小IO,测的是两种性能

磁盘测速绝不能只测一种模式。很多人测完一次顺序写,就得出"这块盘性能很好"的结论,这跟只测了百米冲刺就断言这个人能跑马拉松是一个道理。

存储领域有两个关键指标:

  • 带宽(Bandwidth):单位时间内能传输多少数据,单位是MB/s,主要受顺序读写影响,考验的是磁盘本身的数据传输能力,适合大文件操作场景。
  • IOPS(Input/Output Operations Per Second):每秒能处理多少个IO请求,随机小IO(比如4KB、8KB的数据块)在这种场景下更有代表性,考验的是寻道、队列、并发处理能力,数据库的OLTP业务就是典型场景。

简单说,顺序大IO测"运输能力",随机小IO测"处理事务的能力"。两者都很重要,具体要看你的业务模型是哪一类。忽略这一点的人,很容易被某一种模式下的漂亮数字误导。

2. dd命令的快速验证:能测但别傻测

dd是Linux下最古老的测速工具之一,几乎每台机器都有。它的优点是随手就能用、不需要安装任何东西;缺点是功能太单一,只能模拟最简单的顺序读写,做不了复杂的随机压测。所以我把dd定位为"快速验证工具",它适合初步看个大概水平,不适合做严谨的对比测试。

2.1 用dd测写速度的正确姿势

正确的dd写测试必须强制绕过页缓存,直接在IO层把数据刷到磁盘。这里有两个关键参数:

  • oflag=direct:打开文件时使用O_DIRECT标志,绕过页缓存,数据直接从用户空间写到磁盘设备。
  • conv=fdatasync:测试结束后调用fsync把数据强制落盘。

我常用的完整命令是:

dd if=/dev/zero of=/tmp/disk_test bs=1M count=4096 oflag=direct conv=fdatasync

分解一下每个参数的含义:

  • if=/dev/zero:输入文件是零设备,它会源源不断吐出空字节,避免读盘对测试的影响。
  • of=/tmp/disk_test:输出文件,这里建议放在你真正关心性能的那个挂载点上,写错路径测的就是别的盘了。
  • bs=1M:块大小设为1MB,适合测顺序大IO的带宽。
  • count=4096:一共写4096块,1MB * 4096 = 4GB,这个量够大,能让测试持续一段时间,避免瞬间峰值干扰。
  • oflag=direct:写的时候直接绕过页缓存。
  • conv=fdatasync:确保写完真实落盘才统计时间。

很多人没加direct参数,我也踩过这个坑。建议你也对比测一次,你会看到完全不同的数字。

2.2 用dd测读速度时,必须先清缓存

读测试比写测试更容易失真。因为刚才写到/tmp/disk_test的数据还热乎着,如果立刻去读,它基本都在缓存里,读的全是内存速度。所以测读之前,我要先清一次缓存:

echo 3 > /proc/sys/vm/drop_caches

这条命令会清空页缓存、目录项和inode缓存。执行后需要root权限。清完再执行:

dd if=/tmp/disk_test of=/dev/null bs=1M count=4096 iflag=direct

这里iflag=direct让读数据也绕过页缓存。of=/dev/null是把读出来的数据扔进黑洞设备,避免产生写盘动作干扰结果。走到这一步,dd的读结果才算基本可信。

2.3 dd测出的瓶颈到底是内存还是磁盘

有一个问题很多人忽略:用dd测速时,性能瓶颈可能不在磁盘,而在dd本身是单线程的,它只能用一个CPU核心。数据拷贝、用户态和内核态切换都会消耗CPU,如果磁盘性能很强(比如NVMe SSD),dd单线程反而跑不满盘。

我实测过一块NVMe固态硬盘,用dd测顺序写只能跑出1.5GB/s左右,但后面用fio跑到2.8GB/s以上。原因就是dd单线程成了瓶颈。所以如果你发现dd测出的结果远远低于硬盘标称速度,别急着怀疑盘有问题,先怀疑是不是dd自己跑不动了。

另外,dd测不了随机IO,也测不了混合读写,更测不了并发场景。做完整的读写能力评估,还得看下一节的fio。

3. fio压测:把磁盘的真实水平逼出来

如果说dd是手电筒,那fio就是探照灯。fio是目前Linux系统上最主流、最专业的IO性能测试工具,功能非常全面,几乎所有存储性能测试报告背后都是它。它支持多线程、异步IO、深度队列,能模拟顺序读写、随机读写、混合读写几乎每一种业务IO模型。

3.1 装好fio,用最小脚本跑通全流程

安装很简单,Debian/Ubuntu系:

apt install fio

RedHat/CentOS系:

yum install fio

装好之后,我建议你不要直接去网上抄一堆巨复杂的参数,先跑通最简单的:

fio --name=test \ --filename=/tmp/fio_test \ --rw=write \ --bs=1M \ --size=4G \ --numjobs=1 \ --group_reporting

这条命令的含义是:创建一个4G大小的测试文件,以1M块大小做顺序写,开1个并发进程。跑完之后你会看到类似这样的输出:

write: IOPS=xxx, BW=xxxMiB/s, lat=xxxusec

其中BW是带宽,IOPS是每秒IO次数,lat是延迟。这些概念我们下面细说。

3.2 四种最常见的压测场景与对应参数

fio的--rw参数定义了IO模式,最常用的有四种:

模式参数值适用场景
顺序读read文件读取、视频流媒体、大数据分析扫描
顺序写write日志写入、数据导出、备份落地
随机读randread数据库索引查询、搜索引擎、缓存未命中场景
随机写randwrite数据库日志提交、消息队列、在线事务处理

每种模式背后是一组参数组合,我实际测试时常用这一套来模拟真实的数据库负载:

fio --name=randwrite_test \ --filename=/tmp/fio_randwrite \ --rw=randwrite \ --bs=4k \ --size=2G \ --numjobs=8 \ --iodepth=32 \ --ioengine=libaio \ --direct=1 \ --group_reporting
  • --bs=4k:4KB块大小,这是模拟OLTP数据库典型IO尺寸。
  • --numjobs=8:开8个并发进程,模拟多应用同时访问。
  • --iodepth=32:每个进程保持32个IO请求在队列里排队,这是压满磁盘的常见做法。
  • --ioengine=libaio:使用Linux原生异步IO引擎,磁盘在等待数据时可以同时处理多个请求,模拟真实的并发IO。
  • --direct=1:绕过页缓存,等价于前文说的O_DIRECT。

很多人问为什么随机测要用4k块、iodepth要塞到32?因为随机小IO最考验磁盘的寻道和队列处理能力,如果你的磁盘在队列深度32的情况下都能有不错的IOPS,那实际生产环境大概率不会因为并发IO而卡死。

3.3 fio输出怎么看:带宽、IOPS、时延一个都不能少

fio跑完后输出的信息很多,很多人盯着最后那个BW或IOPS看,其实信息量远不止这些。我每次必看三个指标:

带宽(BW):看的是MB/s,顺序读写场景重点看这个。比如顺序读1000MB/s,顺序写800MB/s,这说明盘在吞吐量上是什么水平。

IOPS:看每秒处理了多少IO请求。随机读写场景重点看这个。比如4k随机读5000多IOPS的机械盘和4k随机读50000多IOPS的SATA固态盘,用得爽不爽直接体现在这里。

时延(lat):这个指标很容易被新手忽略,但生产中它往往最要命。你IOPS再高,如果一次IO平均延迟飙到几百毫秒,数据库照样卡成PPT。重点关注lat的平均值和p99(99%请求的延迟),p99过高意味着偶发长尾延迟,对在线业务影响极大。

我这里有一个真实案例:给某客户做了一套基于普通机械盘的存储方案,顺序读写带宽数据很漂亮,但4k随机读的p99延迟高达800多毫秒,线上数据库一查询就超时。后面换成固态盘,p99降到5毫秒以内,整个业务就顺了。所以读fio结果,一定要三维着看,不要单看一个数字。

fio还能模拟混合读写,比如:

fio --name=rw_mix \ --filename=/tmp/fio_mix \ --rw=rw \ --rwmixread=70 \ --bs=4k \ --size=2G \ --numjobs=4 \ --iodepth=16 \ --ioengine=libaio \ --direct=1 \ --group_reporting

--rwmixread=70表示混合场景下70%是读、30%是写,这是很多业务(比如文件服务器、HTTP服务)的真实负载特征。跑混合测试才能看出磁盘在读和写同时发生时会不会互相拖累,机械盘在这类场景下往往表现很差,因为磁头在读写切换之间损耗极大。

4. hdparm、bonnie++与sysbench:各管一段的补充工具

fio虽然全能,但有些场景下用更轻量的工具反而更合适。这里聊三个我在不同场景下会用的补充工具,它们各自有自己最擅长的位置。

4.1 hdparm:快速读取硬盘参数和缓存性能

hdparm最初是给IDE硬盘调整参数的,现在也支持SATA和大部分SCSI设备。性能测试方面它有两个参数很常用:

hdparm -T /dev/sda

-T测的是Linux缓存读取速度,也就是从内存缓存里读数据的速度,这基本代表的是设备在最佳状态下的表现,也反映内存带宽的一部分。

hdparm -t /dev/sda

-t测的是缓冲读取速度,它读的是设备直接吐出来的数据,比-T更接近磁盘真实性能,但它测的是裸设备,不受文件系统影响。注意,这里的裸设备指的是类似于/dev/sda这种整个块设备,不是某个分区,更不是挂载点。

hdparm还有个好处是可以快速查看磁盘本身的信息:

hdparm -I /dev/sda

这条命令能列出硬盘型号、序列号、支持的传输模式、缓存大小、是否支持TRIM等等,对判断"这块盘是不是SATA 3.0速率"、"缓存多大"很有帮助。不过hdparm对NVMe设备支持并不好,NVMe的盘建议用nvme id-ctrl命令。

4.2 bonnie++:专测文件系统的小文件处理能力

fio测的多数是数据块的读写带宽和延迟,但文件系统除了读写数据,还要创建文件、删除文件、维护目录结构。大量小文件的创建和删除速度,在Web服务器缓存目录、代码仓库、消息堆积目录这类场景下极其重要。bonnie++就是专门测这个的工具。

安装后用法示例:

bonnie++ -d /tmp/bonnie_test -s 2G -n 16 -u root
  • -d:测试目录。
  • -s 2G:测试文件大小2GB。
  • -n 16:测16个文件级别的操作(创建、删除、随机读写等)。

跑完后会输出一个表格,里面的seq-write、seq-rewrite、seq-read是顺序读写性能,random行则是随机创建/删除文件的表现。我一般在评估文件服务器或对象存储时用它,能很快看出来文件系统元数据操作是不是瓶颈。

4.3 sysbench:数据库场景的简单替代方案

sysbench更多被用来做数据库基准测试,但它也集成了文件IO测试模块,可以在不装fio的情况下快速做一个基础的文件读写测试:

sysbench fileio prepare --file-total-size=4G sysbench fileio run --file-test-mode=rndrw --file-total-size=4G --file-io-mode=async --threads=8 sysbench fileio cleanup

三条命令分别是准备测试文件、执行随机读写测试、清理测试文件。sysbench输出的结果比较直观,它会把每类操作的吞吐量、延迟按百分比列出来,对只想快速验证一下存储节点能力的场景来说够用了。

不过说实话,fio功能上基本覆盖了sysbench的文件IO测试,sysbench的优势在于它还能顺带测CPU和内存,适合做整机性能体检。如果只是单独测磁盘,fio还是第一选择。

5. 测了几百台服务器之后,我总结的实战注意事项

工具只是手段,最后测出来的数字能不能用,关键看你会不会控制和解读变量。我这些年陆陆续续帮不同客户测过的服务器、存储塔、云主机没有几百也有一百多台,总结出几个最影响结论准确性的点,单独拿出来说说。

5.1 环境不统一,对比就是耍流氓

很多人喜欢拿"我之前那台旧服务器测出来800MB/s,这台新机器测出来1.2GB/s,所以这台更快"这样的对比。但如果你对比的两组数据,来自不同的文件系统、不同的块大小、不同的队列深度、不同的并发数、不同的测试模式,这个对比结论是站不住脚的。

磁盘测试里,任何一个变量的改变都会直接影响结果。同样一块盘,用4k块测随机读和用1M块测顺序读,数据天差地别;开8个线程和开1个线程,IOPS也可能差出一大截。所以做对比测试前一定要把测试条件固定下来。

我自己的固定套路是:写一个脚本,把fio的参数、测试文件路径、清缓存动作全部固化,每次测试只在盘不同这个变量上做文章。这样才能保证测出来的差异确实来自硬件,而不是来自测试条件。

5.2 SSD和HDD、RAID与硬盘直通,表现差异巨大

不同介质、不同控制卡配置,测出来的数据表现逻辑完全不同,解读的侧重点也不一样:

机械盘(HDD):顺序读写带宽还可以看,但随机IOPS通常只有几十到几百,4k随机读写更是惨不忍睹。这种盘的性能瓶颈在寻道,测的时候要多关注随机IOPS和时延稳定性。

固态盘(SSD):随机IOPS动辄几千上万,顺序读写带宽也高很多。测试时需要注意发热降频问题,有些消费级SSD持续跑几十秒后温度一上来,读写速度会大幅下降。所以测SSD时我习惯让温度先稳定下来,然后跑多轮看稳定后的数据,而不是跑第一次。

RAID阵列:如果磁盘挂在RAID卡上,卡上的缓存策略会直接影响测试结果。常见设置有WriteBack(写回)和WriteThrough(写直通)。WriteBack模式下RAID卡会把写请求先存在卡上的缓存中,然后异步落盘,顺序写性能看起来会非常高;WriteThrough则每次写都直接落盘,性能会下降但数据更安全。测RAID前先搞清楚当前是什么策略,否则用WriteBack测出的写速度可能虚高一截。另外RAID卡本身的BBU(后备电池单元)是否正常、缓存是否够大,都会影响真实性能,测试前建议一块查了。

硬件直通(Pass-Through):如果硬盘直接接在主板SATA口或者用HBA卡直通,没有RAID卡缓存介入,测试结果更能反映硬盘本身的水平,但也更容易被盘自身的写入策略影响。比如某些HDD盘带有写缓存,数据先落DRAM再写盘,测出来的结果和掉电保护场景下的真实表现并不完全一致。

5.3 一个真实调优案例与结果解读的个人经验

最后分享一个我印象最深的磁盘性能排查案例。某客户报障,说他们的文件服务一到高峰期就卡顿,看了CPU和内存都正常,初步怀疑磁盘有问题。我用fio在挂载目录上跑了一轮4k随机读和一轮顺序写,结果非常奇怪:顺序写带宽只有120MB/s,4k随机读IOPS不到500,这两组数据都不像是一块15K转速SAS盘该有的表现。

后来查了半天才发现,这批盘虽然接口是SAS,但实际是RAID卡直通模式下运行的,而且RAID卡上写缓存策略被设成了WriteBack,却没有电池保护模块。也就是说,盘本身的写缓存策略和RAID卡策略打架,导致顺序写像被"阉割"过一样。调整成WriteThrough并关闭部分缓存特性后,顺序写带宽回到900MB/s以上,4k随机读IOPS也恢复到3000+。客户核心问题解决。

这件事给我的经验是:测磁盘,数字不是唯一的判断依据。同样的盘,驱动参数、RAID策略、挂载参数,甚至内核版本,都可能让测试结果产生巨大差异。所以拿结果的时候,永远多问一句:当前环境到底是个什么配置?

给你的建议也很简单:如果只是临时看个大概,dd就够了;如果是做正式的性能评估、容量规划,或者要给客户出报告,请务必用fio把顺序读、顺序写、随机读、随机写、混合读写五个场景全部测一遍,并且记录完整的测试条件。数据才真正有说服力。

我自己测盘时的习惯是:每次测试前先确认测试目录所在挂载点,用df -h看剩余空间,再确认文件系统类型和挂载参数,然后固定一套fio参数跑完整轮,最后把输出保存下来归档。这个习惯帮我省去了很多返工的时间,你也试试。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询