上一篇 下一篇 分享链接 返回 返回顶部

Linux服务器 load average 很高但 CPU 不高怎么办?从 I/O、D 状态进程到数据库阻塞的排查方法

发布人:Minchunlin 发布时间:2026-05-01 09:45 阅读量:450

一、CPU 明明不高,为什么服务器还是“卡”?

服务器运维现场,我经常遇到一种很典型的情况:

网站打开变慢,SSH 登录也有点卡,uptime 一看:

load average: 18.62, 22.15, 19.87
但再看 CPU:
top
发现 CPU 使用率并不高,甚至还有 60% 以上空闲。

很多人第一反应是:“是不是 CPU 不够了?要不要直接换高配机器?”

但实际上,Linux 服务器 load average 高,不一定代表 CPU 被打满
它更像是一个“系统排队压力指标”,不只统计正在抢 CPU 的进程,还会把一部分处于 不可中断睡眠状态,也就是 D 状态 的进程算进去。

所以这类问题的关键不是马上升级 CPU,而是先判断:

服务器到底是在等 CPU,还是在等磁盘、网络、数据库、文件系统、内核资源?

这篇文章我就按一次真实服务器排查思路,把“load 高但 CPU 不高”的排查过程讲清楚。

二、先看懂 load average:它不等于 CPU 使用率

Linux 的 load average 通常有三个值:

load average: 8.20, 12.35, 15.67
分别代表:
指标 含义
1 分钟 load 最近 1 分钟系统平均负载
5 分钟 load 最近 5 分钟系统平均负载
15 分钟 load 最近 15 分钟系统平均负载

很多人误以为 load 就是 CPU 使用率,其实不是。

在 Linux 中,load average 主要统计两类进程:

  1. R 状态进程:正在运行,或者正在等待 CPU 调度。
  2. D 状态进程:不可中断睡眠,通常在等磁盘 I/O、网络文件系统、块设备、内核资源等。

所以会出现这种情况:

CPU idle 70%
load average 30+
这往往说明:

CPU 没有忙死,但系统里有大量进程卡在 I/O、磁盘、文件系统、数据库锁、网络存储或内核等待上。

三、第一步:先判断 load 是否真的异常

不要看到 load 是 8、10、20 就立刻紧张,要结合 CPU 核心数看。

查看 CPU 核心数:

nproc
或者:
lscpu
假设服务器是:
CPU(s): 16
那么:
load 数值 判断
load 4 对 16 核来说不高
load 16 接近满负载,需要关注
load 32 压力明显偏高
load 60 通常已经有阻塞或排队问题

如果是一台 4 核服务器,load 16 就很危险;
但如果是一台 32 核服务器,load 16 可能还没到严重程度。

所以第一句话要记住:

load 要和 CPU 核心数一起看,不能孤立看数字。

四、典型服务器配置场景:不同配置下 load 的意义不一样

以香港服务器业务场景举例,不同硬件配置对 load 的承受能力不同。

服务器类型 示例配置 适合业务 load 判断重点
入门型香港服务器 4 核 / 8G / SSD / 100M BGP 企业官网、小型 WordPress、轻量 API load 超过 4 就要关注
中高性能香港服务器 AMD EPYC 16 核 32 线程 / 64G / NVMe SSD / 100M BGP + 25M CN2 外贸站、跨境电商、接口服务 load 超过 20 才算明显偏高
数据库型服务器 AMD EPYC 24 核 48 线程 / 128G / NVMe RAID / 独享带宽 MySQL、Redis、订单系统 更关注 I/O wait、磁盘延迟、锁等待
大带宽下载 / 图片业务服务器 多核 CPU / 64G+ 内存 / NVMe 或 SSD 阵列 / 1G 带宽 下载站、图片站、视频分发 更关注磁盘吞吐、网卡队列、连接数

如果是普通云服务器,CPU 低但 load 高,可能是磁盘性能或虚拟化资源限制。
如果是物理服务器,尤其是香港独立服务器,更多要关注磁盘 I/O、数据库、备份任务、网络文件系统和异常进程。

五、排查思路总览:不要一上来就重启

遇到 load 高但 CPU 不高,我一般按这个顺序排查:

1. 看 CPU 核心数和 load 是否匹配
2. 看 top 里的 wa、id、st
3. 找 R 状态和 D 状态进程
4. 查磁盘 I/O 是否堵塞
5. 查内存和 swap 是否异常
6. 查数据库、Web 服务、PHP-FPM 是否排队
7. 查网络连接和文件系统
8. 查硬件、内核、磁盘错误
9. 最后再决定是优化,还是升级服务器配置
这个顺序很重要。
因为如果根因是磁盘 I/O 堵塞,你换更强 CPU 没用;如果根因是数据库锁表,你加带宽也没用。

六、先用 top 判断:CPU 是真空闲,还是卡在 I/O wait?

执行:

top
重点看这一行:
%Cpu(s):  8.0 us,  3.0 sy,  0.0 ni, 70.0 id, 18.0 wa, 0.0 hi, 1.0 si, 0.0 st
几个关键字段:
字段 含义 重点判断
us 用户态 CPU 使用率 应用程序消耗 CPU
sy 内核态 CPU 使用率 系统调用、网络、文件系统开销
id CPU 空闲率 id 很高但 load 高,要重点查阻塞
wa I/O wait 磁盘或块设备等待
st steal time 虚拟化环境中被宿主机抢走 CPU

如果你看到:

id 70%
wa 25%
基本可以判断:

CPU 不是瓶颈,磁盘 I/O 或存储层大概率有问题。

如果你看到:

id 80%
wa 0%
st 15%
在云服务器或 VPS 环境里,要怀疑宿主机 CPU 资源被抢占,或者虚拟化层限制。

如果是独立物理服务器,st 一般不会明显偏高。

七、找出 D 状态进程:这是 load 高但 CPU 不高的核心线索

执行:

ps -eo state,pid,ppid,cmd,wchan:32 --sort=state | grep '^D'
如果输出很多类似内容:
D  2314  1208  mysqld             io_schedule
D 4412 2211 php-fpm ext4_file_read_iter
D 5580 1 rsync wait_on_page_bit_common
D 6122 1 tar blk_mq_get_tag
说明有大量进程卡在不可中断等待状态。

常见原因包括:

D 状态来源 可能问题
mysqld 数据库磁盘 I/O 慢、锁等待、临时表落盘
php-fpm 读取文件慢、访问数据库慢、NFS 卡顿
rsync / tar 备份任务压垮磁盘
nginx 静态文件读取慢、日志写入慢
java / node 日志、缓存、数据库连接阻塞
mount / nfs 网络文件系统无响应

也可以统计一下 D 状态数量:

ps -eo state | grep -c D
如果 D 状态进程几十个甚至上百个,而 CPU 使用率不高,那么 load 高基本就不是 CPU 问题。

八、检查磁盘 I/O:最常见的根因

安装工具:

apt install sysstat iotop -y
或者 CentOS:
yum install sysstat iotop -y
查看磁盘 I/O:
iostat -xz 1 5
重点看这些字段:
字段 含义 异常表现
%util 磁盘忙碌程度 长期接近 100% 说明磁盘打满
await I/O 平均等待时间 SSD 超过几十 ms 就要关注
r/s、w/s 每秒读写次数 小文件高并发时会很高
rkB/s、wkB/s 每秒读写吞吐 大文件下载、备份时明显升高
aqu-sz 队列长度 队列越长,等待越严重

例如:

Device    r/s   w/s   await   %util
sda 5.0 320.0 85.3 99.8
这种情况就很明显:

磁盘已经接近满负载,进程大量等待 I/O,load 自然升高。

继续查是谁在读写:

iotop -oPa
或者:
pidstat -d 1
常见“凶手”包括:
mysqld
rsync
tar
gzip
php-fpm
java
nginx
updatedb
backup.sh
logrotate
很多服务器不是被业务打垮的,而是被凌晨备份、日志压缩、MySQL 临时表、图片处理任务拖慢的。

九、检查内存和 swap:CPU 不高也可能是内存不够

查看内存:

free -h
查看 swap 使用:
swapon --show
动态观察:
vmstat 1
重点看:
si so
如果 siso 长时间不为 0,说明系统正在频繁使用 swap。

例如:

procs -----------memory---------- ---swap--
r b swpd free buff cache si so
1 18 4096M 300M 200M 1.2G 25 40
这里的 b 代表阻塞进程数量,si/so 代表 swap in / swap out。

这种情况通常说明:

服务器内存不足,进程被迫频繁换页,磁盘 I/O 被拖慢,load 被拉高。

常见于:

  1. MySQL buffer pool 设置过大。
  2. PHP-FPM 子进程开太多。
  3. Java 堆内存配置不合理。
  4. Redis 没有限制 maxmemory。
  5. 图片、视频处理任务瞬间吃光内存。

十、检查 Web 服务:是不是请求排队了?

如果服务器跑的是 NGINX + PHP-FPM,可以先看连接数:

ss -s
查看 80 / 443 连接:
ss -ant | awk '{print $1}' | sort | uniq -c
重点关注:
ESTAB
SYN-RECV
TIME-WAIT
CLOSE-WAIT
如果 SYN-RECV 很多,可能是攻击、半连接过多或前端防护不足。
如果 CLOSE-WAIT 很多,可能是应用没有正确关闭连接。
如果 ESTAB 很多,说明业务并发较高,需要结合 NGINX、PHP-FPM、数据库一起看。

查看 PHP-FPM 进程:

ps -ylC php-fpm --sort:rss
如果 PHP-FPM 子进程数量太多,每个进程占用几十到几百 MB,内存很容易被吃光。

PHP-FPM 常见优化方向:

pm = dynamic
pm.max_children = 50
pm.start_servers = 8
pm.min_spare_servers = 8
pm.max_spare_servers = 20
pm.max_requests = 500
这里不能照抄,要按内存计算。

比如:

服务器内存:16GB
系统和 MySQL 预留:8GB
可给 PHP-FPM:8GB
单个 PHP-FPM 平均占用:120MB
合理 max_children ≈ 8000 / 120 = 66
如果你设置成 200,很可能不是提升并发,而是把服务器拖进 swap。

十一、检查数据库:很多 load 高其实是 MySQL 卡住了

如果服务器上跑 MySQL,load 高但 CPU 不高,很常见的原因是:

  1. 慢 SQL。
  2. 大表无索引。
  3. 临时表写磁盘。
  4. 磁盘 I/O 被 binlog、redo log、undo log 拖慢。
  5. 表锁或行锁等待。
  6. 备份任务和业务争抢磁盘。

查看 MySQL 当前连接:

mysqladmin processlist
或者进入 MySQL:
SHOW FULL PROCESSLIST;
查看 InnoDB 状态:
SHOW ENGINE INNODB STATUS\G
重点看:
LATEST DETECTED DEADLOCK
TRANSACTIONS
FILE I/O
ROW OPERATIONS
BUFFER POOL AND MEMORY
查看慢查询:
SHOW VARIABLES LIKE 'slow_query_log';
SHOW VARIABLES LIKE 'long_query_time';
建议开启慢日志:
slow_query_log = 1
long_query_time = 1
log_queries_not_using_indexes = 1
如果 MySQL 占用 CPU 不高,但大量 PHP、Java、Node 进程在等待数据库返回,load 一样会升高。

这种时候真正的问题不是 Web 服务,而是数据库响应变慢。

十二、检查备份任务:很多服务器是被“自己人”打满的

我在香港服务器上见过很多类似情况:

白天业务正常,晚上 load 突然升高。
一查发现是:

tar -zcf backup.tar.gz /www/wwwroot
mysqldump --all-databases
rsync -avz /data remote:/backup
这些任务本身没错,但如果没有限速、没有错峰、没有做增量,很容易把磁盘 I/O 打满。

建议备份时加限制。

例如 rsync 限速:

rsync -avz --bwlimit=20000 /data/ backup@remote:/backup/

ionice 降低 I/O 优先级:

ionice -c2 -n7 tar -zcf backup.tar.gz /data

nice 降低 CPU 优先级:

nice -n 19 ionice -c2 -n7 ./backup.sh

如果是数据库备份,尽量避免在业务高峰直接 mysqldump 大库,可以考虑:

  1. 从库备份。
  2. 快照备份。
  3. 分库分表备份。
  4. 低峰期增量备份。
  5. 备份盘和业务盘分离。

十三、检查文件系统和磁盘错误:不要忽略硬件层问题

如果 load 很高、D 状态很多、iowait 高,同时系统日志里有磁盘错误,就要小心硬件问题。

查看内核日志:

dmesg -T | egrep -i "error|fail|reset|timeout|ext4|xfs|nvme|ata|scsi"
查看系统日志:
journalctl -k -p warning
查看硬盘健康:
smartctl -a /dev/sda
NVMe 硬盘:
smartctl -a /dev/nvme0n1
重点关注:
Reallocated_Sector_Ct
Current_Pending_Sector
Offline_Uncorrectable
Media and Data Integrity Errors
Error Information Log Entries
如果出现大量磁盘 timeout、reset、I/O error,说明不是应用层问题,而是硬盘、RAID 卡、线缆、背板、文件系统或阵列异常。

这种情况不要只重启服务,要尽快备份数据并检查硬件。

十四、容器环境下的特殊情况:CPU 不高但被 cgroup 限制

如果业务跑在 Docker、K8s 或容器环境里,还要查 CPU quota。

容器内看 CPU 可能不高,但实际上已经被限制了。

查看容器资源:

docker stats
查看 cgroup CPU 限制:
cat /sys/fs/cgroup/cpu.stat
如果看到 nr_throttled 持续增加,说明进程被 CPU quota 限流。

这种情况表现可能是:

宿主机 CPU 不高
容器内业务响应慢
load 偏高
应用线程排队
解决方向:
  1. 提高容器 CPU limit。
  2. 减少容器内线程数。
  3. 调整 JVM / PHP-FPM / Node worker 数量。
  4. 将数据库、缓存、Web 服务拆开部署。

十五、快速定位命令清单:现场直接照着跑

下面这组命令适合现场快速排查:

uptime
nproc
top
看 load 和 CPU 核心数是否匹配。
ps -eo state,pid,ppid,cmd,wchan:32 --sort=state | grep '^D'
ps -eo state | grep -c D
查 D 状态进程数量。
vmstat 1
看阻塞进程、swap、I/O wait。
iostat -xz 1 5
查磁盘 I/O。
iotop -oPa
pidstat -d 1
找出谁在读写磁盘。
free -h
swapon --show
查内存和 swap。
ss -s
ss -ant | awk '{print $1}' | sort | uniq -c
 查网络连接状态。
dmesg -T | egrep -i "error|fail|timeout|reset|nvme|ata|scsi|ext4|xfs"
查硬件和内核错误。
mysqladmin processlist
查 MySQL 当前连接和阻塞。

十六、不同根因对应的解决方案

1. 磁盘 I/O 打满

表现:

CPU idle 高
load 高
iowait 高
D 状态进程多
iostat %util 接近 100%
解决方案:
  1. 把 HDD 换成 SSD / NVMe。
  2. 数据库和网站文件分盘。
  3. 日志、备份、业务文件分离。
  4. 备份任务加 ionice 和限速。
  5. MySQL 调整 buffer pool,减少临时表落盘。
  6. 高并发图片 / 下载业务使用独立存储盘或对象存储。

适合升级方向:

AMD EPYC 多核 CPU
64G / 128G 内存
960GB NVMe PCIe Gen4 SSD
业务盘 + 备份盘分离
2. 内存不足导致 swap

表现: 

free 可用内存低
swap 使用高
vmstat si/so 持续不为 0
load 高但 CPU 不高
解决方案:
  1. 限制 PHP-FPM 最大子进程数。
  2. 调整 MySQL innodb_buffer_pool_size。
  3. 限制 Redis 最大内存。
  4. 排查 Java / Node 内存泄漏。
  5. 增加物理内存。
  6. 尽量避免业务进程频繁 swap。

配置建议:

普通企业站:16G 内存起步
WordPress + MySQL:32G 更稳
跨境电商 / 订单系统:64G 起步
数据库独立部署:建议 64G / 128G
3. MySQL 慢查询或锁等待

表现:

Web 进程很多
MySQL CPU 不一定高
请求响应慢
load 持续升高
SHOW PROCESSLIST 有大量 Query / Locked / Sending data
解决方案:
  1. 开启慢查询日志。
  2. 补索引。
  3. 避免大表全表扫描。
  4. 优化 JOIN 和排序。
  5. 热点表拆分。
  6. 数据库和 Web 服务分离。
  7. 使用 Redis 缓存热点数据。

配置建议:

Web 服务器:16 核 / 32G / NVMe
数据库服务器:24 核 / 64G 或 128G / NVMe RAID
数据库尽量不要和备份、日志、大文件下载混跑
 4. 备份任务压垮服务器

表现:

凌晨 load 高
tar / gzip / rsync / mysqldump 占用 I/O
iowait 高
业务访问变慢
解决方案:
  1. 备份任务错峰执行。
  2. 使用 ionice 降低 I/O 优先级。
  3. 使用增量备份。
  4. 限制 rsync 带宽。
  5. 业务盘和备份盘分离。
  6. 大库使用从库或快照备份。

5. 网络文件系统或远程存储卡顿

表现:

D 状态进程很多
wchan 显示 nfs / fuse / wait_on_page
本地 CPU 和磁盘都不高
访问挂载目录很慢
 解决方案:
  1. 检查 NFS、对象存储挂载、远程备份目录。
  2. 避免业务主路径依赖不稳定远程挂载。
  3. 设置合理 timeout。
  4. 重要业务文件放本地 NVMe。
  5. 远程存储只做备份,不做实时业务目录。

十七、什么时候需要升级服务器配置?

不是所有 load 高都要升级,但出现下面情况时,就要认真考虑换配置。

情况一:磁盘 I/O 长期打满

如果业务高峰期:

iostat %util 长期 90%+
await 持续偏高
D 状态进程持续增加
这时候优化空间有限,应该升级到 NVMe SSD,或者做磁盘分离。

推荐方向:

AMD EPYC 16 核 32 线程
64G DDR4
960GB NVMe PCIe Gen4 SSD
100M BGP + 25M CN2 直连
适合:
WordPress 外贸站
跨境电商独立站
中等访问量 API
企业官网集群节点
 情况二:数据库和 Web 混跑互相影响

如果一台服务器同时跑:

NGINX
PHP-FPM
MySQL
Redis
备份任务
图片处理
日志分析
 一旦访问量上来,任何一个环节异常都会把 load 拉高。

建议拆分为: 

Web 前端服务器
数据库服务器
缓存服务器
备份服务器
 数据库服务器推荐:
AMD EPYC 24 核 48 线程
64G / 128G DDR4
NVMe SSD
独立内网连接
 这样 Web 层卡顿不会直接拖死数据库,数据库压力也不会影响静态资源和 PHP 请求。

情况三:业务并发明显增长

比如原来每天几千 IP,现在增长到几万 IP;
原来只是企业官网,现在变成跨境电商、接口服务、会员系统。

这时候 load 高可能不是故障,而是服务器配置已经接近上限。

升级建议:

业务类型 推荐配置
普通企业站 4 核 / 8G / SSD
WordPress 外贸站 8 核 / 16G / SSD 或 NVMe
跨境电商独立站 16 核 / 32G 或 64G / NVMe
数据库业务 24 核 / 64G 或 128G / NVMe
下载 / 图片业务 多核 CPU / 大内存 / NVMe / 1G 带宽
高并发 API 多台 Web + 独立 DB + Redis

十八、一个真实排查案例:load 40,但 CPU 只有 20%

有一次,一台香港服务器出现访问卡顿。

服务器配置大概是:

CPU:AMD EPYC 16 核 32 线程
内存:64GB DDR4
硬盘:960GB NVMe SSD
带宽:100M BGP,含 25M CN2 直连
系统:Ubuntu 22.04
业务:WordPress + WooCommerce + MySQL
客户反馈网站后台打开很慢,前台偶尔 502。

现场看到:

load average: 38.21, 42.16, 36.80
但 top 里 CPU 并不高:
us 12%
sy 5%
id 58%
wa 24%
继续查:
ps -eo state,pid,cmd,wchan:32 | grep '^D'
发现大量: 
php-fpm
mysqld
rsync
再看磁盘:
iostat -xz 1 5
结果:
%util 99%
await 80ms+
 最后发现原因是:
凌晨备份脚本没有结束
rsync 正在同步大量图片
同时 mysqldump 还在导出数据库
WooCommerce 后台又在生成报表
 这不是 CPU 问题,而是磁盘 I/O 被多个任务挤爆。

处理方式:

  1. 立即暂停 rsync。
  2. 停止重复 mysqldump。
  3. 将备份任务调整到低峰。
  4. rsync 加 --bwlimit
  5. 备份脚本加 ionice
  6. MySQL 慢日志开启。
  7. WooCommerce 报表任务错峰执行。
  8. 后续将备份目录迁移到独立磁盘。

处理后:

load 从 40+ 降到 5-8
CPU 使用率保持 20%-35%
网站后台恢复正常
这个案例说明:

load 高不一定是 CPU 不够,很多时候是磁盘、数据库和备份任务在互相抢资源。

十九、最终判断逻辑:一句话总结

遇到 Linux 服务器 load average 很高但 CPU 不高,可以按这个逻辑判断:

CPU 不高 + iowait 高 = 优先查磁盘 I/O
CPU 不高 + D 状态多 = 查阻塞进程和文件系统
CPU 不高 + swap 高 = 查内存不足
CPU 不高 + MySQL 连接堆积 = 查慢 SQL 和锁等待
CPU 不高 + 夜间异常 = 查备份、日志、定时任务
CPU 不高 + 容器环境 = 查 cgroup 限制
CPU 不高 + dmesg 报错 = 查硬盘、RAID、文件系统
 不要看到 load 高就直接加 CPU。
真正专业的处理方式是先找出进程在等什么。

二十、load 高不是一个点的问题,而是整台服务器的排队信号

Linux 的 load average 很像服务器的“排队长度”。
CPU 不高但 load 高,往往说明服务器不是算不动,而是某些资源被卡住了。

对于网站、数据库、跨境电商、API 服务来说,真正影响稳定性的通常不是单一 CPU 指标,而是:

CPU 调度
磁盘 I/O
内存和 swap
数据库锁
PHP-FPM 队列
备份任务
文件系统
网络连接
硬件健康
 如果只是短时间 load 升高,可以先观察。
如果 load 长期高于 CPU 核心数,并且伴随网站变慢、SSH 卡顿、数据库响应变慢,就必须按上面的链路系统排查。

服务器优化的核心不是盲目升级,而是先判断瓶颈在哪里。
该优化 SQL 就优化 SQL,该换 NVMe 就换 NVMe,该拆数据库就拆数据库,该升级多核高内存物理服务器时也不要硬撑。

这样处理,才能真正让 Linux 服务器稳定下来

 

目录结构
全文