我要提问
ARTICLE DETAIL

资讯详情

前沿编程新知与开发实战干货的深度解读。

Linux磁盘读写测试全攻略:dd、fio与实战避坑指南

Linux磁盘读写测试全攻略:dd、fio与实战避坑指南 最近帮客户排查一台数据库服务器性能问题时发现了一个很有意思的现象系统负载不高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 bs1M count2048这条命令在多数机器上跑出来可能每秒好几个GB你看了很高兴但实际上/tmp/speedtest这个文件的大部分数据还在页缓存里泡着根本没落盘。这时候你拔电源文件大概率是坏的。正确的测法我们后面讲这里你只需要记住测试工具的结果不代表磁盘真实速度必须主动绕开缓存才能测到真实水平。1.3 顺序大IO和随机小IO测的是两种性能磁盘测速绝不能只测一种模式。很多人测完一次顺序写就得出这块盘性能很好的结论这跟只测了百米冲刺就断言这个人能跑马拉松是一个道理。存储领域有两个关键指标带宽Bandwidth单位时间内能传输多少数据单位是MB/s主要受顺序读写影响考验的是磁盘本身的数据传输能力适合大文件操作场景。IOPSInput/Output Operations Per Second每秒能处理多少个IO请求随机小IO比如4KB、8KB的数据块在这种场景下更有代表性考验的是寻道、队列、并发处理能力数据库的OLTP业务就是典型场景。简单说顺序大IO测运输能力随机小IO测处理事务的能力。两者都很重要具体要看你的业务模型是哪一类。忽略这一点的人很容易被某一种模式下的漂亮数字误导。2. dd命令的快速验证能测但别傻测dd是Linux下最古老的测速工具之一几乎每台机器都有。它的优点是随手就能用、不需要安装任何东西缺点是功能太单一只能模拟最简单的顺序读写做不了复杂的随机压测。所以我把dd定位为快速验证工具它适合初步看个大概水平不适合做严谨的对比测试。2.1 用dd测写速度的正确姿势正确的dd写测试必须强制绕过页缓存直接在IO层把数据刷到磁盘。这里有两个关键参数oflagdirect打开文件时使用O_DIRECT标志绕过页缓存数据直接从用户空间写到磁盘设备。convfdatasync测试结束后调用fsync把数据强制落盘。我常用的完整命令是dd if/dev/zero of/tmp/disk_test bs1M count4096 oflagdirect convfdatasync分解一下每个参数的含义if/dev/zero输入文件是零设备它会源源不断吐出空字节避免读盘对测试的影响。of/tmp/disk_test输出文件这里建议放在你真正关心性能的那个挂载点上写错路径测的就是别的盘了。bs1M块大小设为1MB适合测顺序大IO的带宽。count4096一共写4096块1MB * 4096 4GB这个量够大能让测试持续一段时间避免瞬间峰值干扰。oflagdirect写的时候直接绕过页缓存。convfdatasync确保写完真实落盘才统计时间。很多人没加direct参数我也踩过这个坑。建议你也对比测一次你会看到完全不同的数字。2.2 用dd测读速度时必须先清缓存读测试比写测试更容易失真。因为刚才写到/tmp/disk_test的数据还热乎着如果立刻去读它基本都在缓存里读的全是内存速度。所以测读之前我要先清一次缓存echo 3 /proc/sys/vm/drop_caches这条命令会清空页缓存、目录项和inode缓存。执行后需要root权限。清完再执行dd if/tmp/disk_test of/dev/null bs1M count4096 iflagdirect这里iflagdirect让读数据也绕过页缓存。of/dev/null是把读出来的数据扔进黑洞设备避免产生写盘动作干扰结果。走到这一步dd的读结果才算基本可信。2.3 dd测出的瓶颈到底是内存还是磁盘有一个问题很多人忽略用dd测速时性能瓶颈可能不在磁盘而在dd本身是单线程的它只能用一个CPU核心。数据拷贝、用户态和内核态切换都会消耗CPU如果磁盘性能很强比如NVMe SSDdd单线程反而跑不满盘。我实测过一块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 fioRedHat/CentOS系yum install fio装好之后我建议你不要直接去网上抄一堆巨复杂的参数先跑通最简单的fio --nametest \ --filename/tmp/fio_test \ --rwwrite \ --bs1M \ --size4G \ --numjobs1 \ --group_reporting这条命令的含义是创建一个4G大小的测试文件以1M块大小做顺序写开1个并发进程。跑完之后你会看到类似这样的输出write: IOPSxxx, BWxxxMiB/s, latxxxusec其中BW是带宽IOPS是每秒IO次数lat是延迟。这些概念我们下面细说。3.2 四种最常见的压测场景与对应参数fio的--rw参数定义了IO模式最常用的有四种模式参数值适用场景顺序读read文件读取、视频流媒体、大数据分析扫描顺序写write日志写入、数据导出、备份落地随机读randread数据库索引查询、搜索引擎、缓存未命中场景随机写randwrite数据库日志提交、消息队列、在线事务处理每种模式背后是一组参数组合我实际测试时常用这一套来模拟真实的数据库负载fio --namerandwrite_test \ --filename/tmp/fio_randwrite \ --rwrandwrite \ --bs4k \ --size2G \ --numjobs8 \ --iodepth32 \ --ioenginelibaio \ --direct1 \ --group_reporting--bs4k4KB块大小这是模拟OLTP数据库典型IO尺寸。--numjobs8开8个并发进程模拟多应用同时访问。--iodepth32每个进程保持32个IO请求在队列里排队这是压满磁盘的常见做法。--ioenginelibaio使用Linux原生异步IO引擎磁盘在等待数据时可以同时处理多个请求模拟真实的并发IO。--direct1绕过页缓存等价于前文说的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的平均值和p9999%请求的延迟p99过高意味着偶发长尾延迟对在线业务影响极大。我这里有一个真实案例给某客户做了一套基于普通机械盘的存储方案顺序读写带宽数据很漂亮但4k随机读的p99延迟高达800多毫秒线上数据库一查询就超时。后面换成固态盘p99降到5毫秒以内整个业务就顺了。所以读fio结果一定要三维着看不要单看一个数字。fio还能模拟混合读写比如fio --namerw_mix \ --filename/tmp/fio_mix \ --rwrw \ --rwmixread70 \ --bs4k \ --size2G \ --numjobs4 \ --iodepth16 \ --ioenginelibaio \ --direct1 \ --group_reporting--rwmixread70表示混合场景下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-size4G sysbench fileio run --file-test-moderndrw --file-total-size4G --file-io-modeasync --threads8 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/s4k随机读IOPS不到500这两组数据都不像是一块15K转速SAS盘该有的表现。后来查了半天才发现这批盘虽然接口是SAS但实际是RAID卡直通模式下运行的而且RAID卡上写缓存策略被设成了WriteBack却没有电池保护模块。也就是说盘本身的写缓存策略和RAID卡策略打架导致顺序写像被阉割过一样。调整成WriteThrough并关闭部分缓存特性后顺序写带宽回到900MB/s以上4k随机读IOPS也恢复到3000。客户核心问题解决。这件事给我的经验是测磁盘数字不是唯一的判断依据。同样的盘驱动参数、RAID策略、挂载参数甚至内核版本都可能让测试结果产生巨大差异。所以拿结果的时候永远多问一句当前环境到底是个什么配置给你的建议也很简单如果只是临时看个大概dd就够了如果是做正式的性能评估、容量规划或者要给客户出报告请务必用fio把顺序读、顺序写、随机读、随机写、混合读写五个场景全部测一遍并且记录完整的测试条件。数据才真正有说服力。我自己测盘时的习惯是每次测试前先确认测试目录所在挂载点用df -h看剩余空间再确认文件系统类型和挂载参数然后固定一套fio参数跑完整轮最后把输出保存下来归档。这个习惯帮我省去了很多返工的时间你也试试。
返回列表