磁盘吞吐不足的本质是存储设备在单位时间内能搬运的数据量跟不上业务请求,这不是单纯换一块更快的硬盘就能解决的,先分清瓶颈出在单盘性能、协议开销还是队列调度,再动手优化。
磁盘吞吐不足的典型症状是什么
磁盘吞吐不足拖慢数据加载的时候,系统并不是直接蓝屏或者报错,而是像一个人干活时被卡住了手:表面看还在运行,但每一步都慢半拍,这种问题比CPU高负载更难察觉,也更容易被误判成程序写法有问题。
数据加载慢得不像网速问题
一个很常见的变化是:应用连接的数据库响应有时快、有时慢,跑一批报表要等半天,排查的时候,网络延迟看着正常,CPU占用也不高,最后才发现是磁盘扛不住了。
典型表现包括:
- 从数据库导入导出数据时,进度条长时间卡住不动
- 应用日志写入出现明显延迟,日志文件增长缓慢但请求队列很长
- 缓存未命中时,从磁盘拉数据比平时慢几倍甚至十几倍
我记得之前有个做电商的朋友反馈,说后台的订单导出功能一到晚上就特别慢,他原本以为是带宽不给力,结果我把导出路径的临时文件放在SSD上,速度立刻提升了,问题根源就是用的传统机械盘,磁盘吞吐量低是什么原因很简单几百个并发同时读同一个磁盘,机械盘的磁头来回寻道,速度自然会掉到惨不忍睹。
数据库查询突然变卡
数据库对随机读的要求比较高,这块也是重灾区,如果你用的是MySQL这类关系型数据库,且表的数据量已经膨胀到内存装不下了,查询时肯定需要从磁盘读索引和数据页。
此时你可以观察一个指标iostat里的await,这个值代表I/O请求的平均处理时间,如果长期超过30毫秒,甚至到了几百毫秒,说明磁盘已经在排队了,行业共识认为,磁盘队列中一旦出现积压,整体吞吐会呈断崖式下降,而不是线性变慢。
大数据任务时间翻倍
跑Spark或者Hadoop任务时,中间结果要频繁落盘,shuffle阶段更是会把数据反复写进临时目录,如果临时目录正好放在一块吞吐能力不足的磁盘上,整个任务的计算时间会被拖到原来的两到三倍。
这种场景下,你去看监控,CPU使用率其实很低,但任务就是跑不动,原因是资源都耗在等待磁盘I/O上。
磁盘吞吐量低是什么原因
说到根因,业内专家指出,磁盘其实并不可怕,可怕的是你根本没了解它到底擅长什么,磁盘吞吐量低,无非以下几种情况。
单盘性能到顶
机械硬盘的顺序读写速度一般在100到200 MB/s之间,随机读写更是只有个位数MB/s级别,SATA SSD稍微好一些,顺序读写能到500 MB/s左右,但随机IOPS也有上限,NVMe SSD是目前消费级的天花板,顺序读写轻松超过2000 MB/s。
如果业务要求就是持续大流量读写,比如视频渲染、日志收集,那你用一块老旧的机械盘来做主力存储,性能就是天然不够的。
协议和挂载方式拖后腿
很多应用跑在云主机上,磁盘是网络云盘,云盘的吞吐能力受限于网络带宽和虚拟化层,和本地NVMe盘根本不是一个量级,举个例子:本地盘的时延在几十微秒到一百微秒,而网络云盘的时延直接到毫秒级,差了百倍。
文件系统挂载参数也会影响吞吐,ext4默认的挂载选项和XFS在高并发场景下的表现有差异;NFS、SMB协议挂载的共享存储,还要额外承受协议本身的开销。
队列深度和碎片问题
机械盘有磁头和盘片,写文件时会形成文件碎片,碎片多了,读写时磁头来回跳,吞吐自然上不去,SSD虽然没有物理寻道时间,但垃圾回收、磨损均衡也会在某些时候拖慢速度。
还有一点容易被忽略:操作系统的I/O调度器,不同的调度器(比如CFQ、noop、deadline,新版内核的mq-deadline和none)在不同场景下表现不一样,很多默认配置追求的是公平,但我们实际需要的是优先处理数据库这类延迟敏感的业务请求。
磁盘吞吐不足怎么解决:从定位到实操
别一上来就买新硬盘,先按下面这套流程定位问题。磁盘吞吐不足怎么解决,核心是“先诊断,后对症”。
先用工具看清楚是谁在拖后腿
最直接的命令是iostat,你可以这么用:
iostat -x 1
重点看几个字段:
- rKB/s和wKB/s:判断读写量有多大
- %util:磁盘是否长时间处于忙碌状态,超过80%就要警惕了
- avgqu-sz:队列长度,正常应该很小,如果长期大于2,说明I/O在排队
- await:响应时间,机械盘超过30ms、SSD超过5ms都算异常
如果需要定位是哪个进程在读写,用iotop查看:
sudo iotop -o
这一步能看到每个进程实际占用的I/O带宽,避免乱猜,如果你想测试整块盘的真实性能上限,用fio:
fio -filename=/tmp/testfile -direct=1 -iodepth 32 -rw=randread -bs=4k -size=1G -numjobs=4 -runtime=60 -group_reporting -name=test
这能测出磁盘的随机读IOPS,是最有说服力的验证方法,测完你就知道手上的盘到底哪一步性能不足,而不是凭感觉说“慢”。
业务层怎么调整最见效
诊断完之后,有些问题其实不用换硬件就能缓解。
数据库场景可以做读写分离,把读流量导到备库,主库专心跳写,如果框架允许,尽量用批量查询,减少单条SQL往返,对于MySQL,可以适当调大innodb_buffer_pool_size,让缓存命中率上去,减少磁盘读压力。
日志类业务优化空间更大,日志写入推荐顺序追加,不要频繁小规模写入,如果要追求极致的写入速度,可以先把日志写在本地临时盘,再异步同步到远端,中间加个缓冲层把数据攒成大批量再写。
文件服务场景,可以把热点小文件合并成大文件存储,减少随机小I/O,大文件的顺序读吞吐明显优于小文件的随机读。
硬件层面有哪些选择
如果业务增长确实快,当前磁盘已经无法满足需求,那选型上要做个对比。
| 存储类型 | 顺序读写速度 | 随机IOPS表现 | 适用场景 |
|---|---|---|---|
| 机械盘HDD | 100-200 MB/s | 较差,单位数到百位数 | 冷数据备份、低成本归档 |
| SATA SSD | 约500 MB/s | 中等,千位数左右 | 普通业务存储、本地文件 |
| NVMe SSD | 2000 MB/s以上 | 很高,万级以上 | 数据库、高并发应用 |
HDD和SSD吞吐能力差多少
HDD和SSD吞吐能力差多少,你用实际压测数据说话最直观,给一台业务服务器同时挂一块机械盘和一块NVMe盘,跑同一个数据加载任务,机械盘耗时如果是10分钟,NVMe盘通常只需要30秒到1分钟。
机械盘的真实表现
机械盘的瓶颈在于物理结构,盘片转速越快,读写速度越高,但也就那样了,目前市面上主流的7200转企业级机械盘,顺序读取在200 MB/s左右,一旦涉及随机读写,IOPS会掉到一两百,这数据放到今天的业务环境里,已经完全跟不上节奏。
SATA SSD的性价比
SATA SSD本质上是把SATA接口的带宽吃满了,顺序速度被卡在约550 MB/s,但因为它是闪存介质,随机读取能力比机械盘强不少,价格方面,同等容量下比NVMe便宜不少,在预算有限的情况下是个折中的升级方案。
NVMe的时代
NVMe走的已经不是传统AHCI协议了,PCIe通道直连CPU,延迟低、队列深度高,价格虽然比SATA SSD高一些,但它的吞吐和IOPS远超SATA SSD,而且现在的价格对比几年前已经降了很多,如果你在运营一个高并发的在线服务,多花一点钱把存储换成NVMe,是最立竿见影的升级手段。
预防磁盘吞吐再次成为瓶颈
优化做完不等于一劳永逸,存储的性能会随着数据量的增长再次暴露出来,把下面几件事做成常规动作,就不会等到火烧眉毛才想起检查。
监控放在前面
先把iostat、iotop这些工具接进监控系统,比如部署Prometheus时加上node_exporter的磁盘指标,给await、util、avgqu-sz设好告警阈值,别等用户反馈说页面打不开了,才临时去服务器上敲命令。
预留缓冲和缓存层
给热点数据加一层Redis或者本地缓存,能挡掉很大一部分磁盘读压力,写操作如果不需要实时落盘,可以考虑在业务层做异步落盘,把随机频繁写变成批量的顺序写,同时预留20%到30%的磁盘空闲空间,尤其是SSD,空间占用太满会严重影响写入性能。
磁盘吞吐不足是存储系统最典型的结构性瓶颈,它的修复不是一次操作,而是一套持续的预案,记住一点:先判断瓶颈层级,再决定优化手段,大多数情况下答案藏在“调度”和“缓存”里,而不只在新硬件上。
磁盘吞吐不足相关问题解答
怎么判断是磁盘吞吐不足还是应用代码问题?
先看iostat的avgqu-sz和%util,如果队列长度超过2且util长期高于80%,大概率是磁盘层问题,如果这些指标正常但慢,问题在应用层,用perf或arthas检查锁等待、慢SQL和网络调用即可。
数据库迁移到SSD后吞吐没提升怎么办?
检查文件系统是否对齐,SSD需要4K对齐,确认SSD的固件版本是否最新,同时看看I/O调度器是否设置为none或mq-deadline,还可以调大innodb_io_capacity和innodb_io_capacity_max的值,让MySQL充分利用SSD的IOPS,做完这些再重启数据库观察效果。
为什么RAID卡下的SSD反而跑不快?
RAID卡自带的缓存和写策略可能成了瓶颈,比如写回策略未开启,或者RAID卡本身的缓存太小,反而限制了SSD的随机写性能,确认RAID卡设置为直通(HBA模式)或者开启写缓存,同时更新RAID卡驱动和固件,部分老RAID卡对SSD Trim命令兼容性不好,同样会影响性能和寿命。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/623205.html





