load 飙到 24 CPU 却闲着:一次 Linux 高负载排查复盘

监控告警一台 8 核服务器 load average 飙到 24,SSH 上去 top 一看 CPU 空闲却有 88%,负载高得像要炸机 CPU 却闲得像在午休。排查梳理:load average 不是 CPU 使用率,它数的是系统里 R 运行可运行和 D 不可中断睡眠状态的进程数量;D 状态进程在等磁盘 IO,它睡着没在用 CPU 却照样被算进 load,这就是 load 高 CPU 闲的根源;load 的绝对值要除以 CPU 核数才有意义,load 除核数大于 1 才说明真有任务在排队;load 高先定性,看 top 的 id 高还是低、wa 有没有值,再数 D 状态进程,id 高加一堆 D 是 IO 型高负载、id 低 us/sy 高是 CPU 型;判断 IO 型更可靠的信号是 D 状态进程数量而不是只看 iowait;IO 型用 iostat -x 找 %util 贴近 100 await 很大的盘,再用 pidstat -d 找狂打 IO 的元凶进程;D 状态进程在等内核级 IO 操作拒绝被信号唤醒,kill -9 也杀不动要去治那个慢 IO;别看见高 load 就重启,重启只清现场病根没动;正确解法是按 CPU 型和 IO 型分别对症、优化 SQL 日志或换更快的盘、配监控同时采集 CPU 和磁盘指标、留快照脚本,以及一套负载排查纪律。

2024 年的一个下午,监控突然给我推了一条告警:某台服务器的 load average 飙到了 24。我一看就慌了——这台机器是 8 核的,负载 24,意味着平均每个核上排着 3 个任务等着跑,在我的理解里,这就是 CPU 被彻底榨干、机器要"烧"起来的节奏。我立刻 SSH 上去,准备抓出那个吃满 CPU 的进程。可 top 一打开,我愣住了:最上面那行 load average 确实是 24, 22, 20,高得吓人;可 CPU 那一行,id(空闲)居然是 88%——CPU 有将近九成是闲着的。我把进程列表按 CPU 排了序,排在最前面的进程,CPU 占用也才个位数。这个画面彻底拧巴了:负载高得像要炸机,CPU 却闲得像在午休。我一度怀疑是 top 显示出了 bug,反复刷新、换 uptime、直接 cat /proc/loadavg 去看——load 就是实打实的 24,CPU 就是实打实的闲。"负载"和"CPU 使用率",这两个我一直以为是同一回事、至少是高度同步的东西,此刻在我眼前彻底分了家。我盯着这个矛盾想了很久,最后才意识到:我从一开始就把 load average 这个数字的含义,理解错了。这件事逼着我把 load average 到底数的是什么、D 状态、iowait 这一整套彻底理清了。本文复盘这次实战。

问题背景

环境:CentOS 7,8 核的应用服务器
事故现象:
- ★ load average 飙到 24, 22, 20(8 核机器)
- ★ 可 top 里 CPU 空闲(id)有 88%,几乎没在干活
- 按 CPU 排序,最忙的进程也才占个位数

现场排查:
# 1. load 确实高
$ uptime
 15:42:01 up 90 days,  load average: 24.31, 22.10, 20.05
#                                    ^^^^^ ★ 8 核机器,这值高得离谱

# 2. ★ 可是 CPU 几乎是闲的
$ top
%Cpu(s):  5.1 us,  3.2 sy,  0.0 ni, 88.0 id,  3.5 wa, ...
#                                   ^^^^^^^ ★ 88% 空闲
#                                            ^^^^^ ★ wa(iowait)有值

# 3. ★ 关键一招:看进程都处在什么状态
$ ps -eo stat,comm | awk '{print $1}' | sort | uniq -c | sort -rn
   210 S          # 睡眠(正常)
    22 D          # ★ 不可中断睡眠 —— 22 个!可疑
     3 R          # 真正在运行 / 可运行的,才 3 个
#  ^^ ★ 22 个进程卡在 D 状态

# 4. ★ D 状态进程在等什么 —— 几乎都在等磁盘 IO
$ ps -eo pid,stat,comm | awk '$2 ~ /D/'
12011 D  mysqld
12044 D  java
12077 D  java
...(22 个,全是在做磁盘读写的进程)

# 5. ★ 看磁盘 IO,果然压满了
$ iostat -x 1 3
Device  r/s   w/s   %util  await
vdb     0.0   880   99.7   420.0
#                   ^^^^^  ^^^^^ ★ 磁盘 100% 忙,单次 IO 等 420ms

根因(后来想清楚的):
1. ★ Linux 的 load average,数的【不是】 CPU 使用率。
   它数的是"系统里处于 R(运行/可运行)和
   D(不可中断睡眠)状态的进程数量"的平均值。
2. ★ 关键就在那个 D 状态:一个进程在【等磁盘 IO】
   时,会进入 D 状态。它【没在用 CPU】(它在睡),
   但它【照样被算进 load】。
3. 这台机器的磁盘那会儿被打满了(%util 99.7%),
   22 个进程一起卡在"等磁盘"上,全是 D 状态。
4. ★ 于是:这 22 个 D + 3 个 R = load 直奔 24。
   可它们里 22 个都在睡(等 IO),根本不烧 CPU——
   CPU 自然显示 88% 空闲。
5. 我的错:把 load 当成了"CPU 有多忙"。其实 load
   高,可能是 CPU 忙,也可能是【IO 把进程卡住了】。
load 高 ≠ CPU 忙。这次的 load 高,是磁盘 IO 拖的,不是 CPU。

修复 1:load average 到底数的是什么

# === ★ 纠正最大的误解:load 不是"CPU 使用率" ===

# === 我以为的 vs 真实的 ===
# 我以为:load average 就是 CPU 的繁忙程度。load 24
#   = CPU 被 24 个任务挤爆了 = CPU 要烧了。
# ★ 真相:Linux 的 load average,统计的是【一段时间内,
#   系统里处于这两种状态的进程数量】的平均:
#  - R 状态:正在 CPU 上跑,或【就绪、排队等 CPU】。
#  - D 状态:★ 不可中断睡眠 —— 绝大多数是【在等 IO】
#    (等磁盘、等网络存储)。
# ★ 注意第二条:D 状态的进程【没在用 CPU】(它在睡),
#   但它【被算进 load】。这就是 load 和 CPU 能分家的
#   根本原因。

# === ★ 别的系统不一样 ===
# 提一句:其他 Unix(如 BSD)的 load 只数 R 状态。
#   ★ 是 Linux 特意把 D 状态也算了进来 —— 它想表达的
#   是"系统整体有多少任务被卡住、推不动",而不只是
#   "CPU 有多忙"。所以 Linux 的 load,本质是
#   【系统繁忙度 / 拥堵度】,不是【CPU 利用率】。

# === ★ load 的三个数字 ===
$ cat /proc/loadavg
24.31 22.10 20.05 3/235 13001
# 前三个:过去 1 分钟、5 分钟、15 分钟的平均 load。
# ★ 三个数一起看,能看出趋势:
#  - 1分 > 5分 > 15分 -> 负载正在【上升】。
#  - 1分 < 5分 < 15分 -> 负载正在【回落】。
# 第四个 3/235:当前可运行进程数 / 总进程数。

# === ★ load 多少算高?要除以核数 ===
# load 的绝对值,必须对照【CPU 核数】才有意义:
$ nproc
8
# ★ 经验线:load / 核数
#  - ≈ 1   :系统刚好饱和。
#  - < 0.7 :有余量,健康。
#  - > 1   :有任务在排队等(等 CPU,或等 IO)。
# 我这次:load 24 / 8 核 = 3 —— 严重拥堵。但拥堵在
#   哪,还得往下查。

# === 认知 ===
# ★ load 高,只说明"系统里被卡住/排队的任务多"。
#   它【没告诉你】卡在哪 —— 是卡在 CPU,还是卡在 IO。
#   把 load 高直接等同于"CPU 忙",是这次最大的错。

修复 2:load 高,先分清是"CPU 型"还是"IO 型"

# === ★ load 高的两种类型,排查方向完全不同 ===

# === 两种"高 load",一眼区分 ===
# load 高,无非两种情况,看 top 的 CPU 那一行就能分:
#
# 类型 A:CPU 型高负载
#   特征:CPU 的 id(空闲)很低、us/sy 很高。
#   含义:真的是【活儿太多,CPU 跑不过来】,一堆
#     R 状态进程在排队等 CPU。
#
# 类型 B:★ IO 型高负载(我这次)
#   特征:CPU 的 id 很高(看着很闲)、但 wa 有值,
#     而且有一堆 D 状态进程。
#   含义:进程【不是在等 CPU,是在等 IO】。CPU 没事
#     干(所以 id 高),但任务都被慢 IO 卡住了。

# === ★ 第一现场:top 的 CPU 行怎么读 ===
$ top
%Cpu(s):  5.1 us,  3.2 sy,  0.0 ni, 88.0 id,  3.5 wa,  0.2 hi, 0.0 si
#          ^^us  用户态     ^^sy 内核态
#                              ^^^id 空闲
#                                       ^^^wa ★ iowait
# ★ us+sy 高、id 低  -> 类型 A,CPU 真忙。
# ★ id 高、wa 有值   -> 类型 B,CPU 闲、卡在 IO。
# 我这次 id=88%,矛头明确指向【不是 CPU 的问题】。

# === ★ 关于 wa(iowait)的一个澄清 ===
# wa 高,确实提示"有 IO 在等";但 wa 低,★ 不代表
#   没有 IO 问题。iowait 的统计有点微妙:如果 CPU
#   被别的活儿占着,等 IO 的时间可能没算进 wa。
# ★ 所以判断 IO 型负载,【更可靠的信号是 D 状态进程
#   的数量】,而不是只盯着 wa 这个数。

# === ★ 决定性一招:数 D 状态进程 ===
$ ps -eo stat | grep -c '^D'
22                                    # ★ 22 个 D 状态
# 或更直观地看分布:
$ ps -eo stat,comm | awk '{print substr($1,1,1)}' \
    | sort | uniq -c | sort -rn
# ★ 如果 D 这一类有一大堆 —— 基本就是 IO 型高负载,
#   往磁盘 / 网络存储那边查(修复 3)。
# ★ 如果几乎全是 R —— 那是 CPU 型,往"谁在吃 CPU"
#   那边查(修复 5)。

# === 认知 ===
# ★ 看到 load 高,第一个动作不是去抓 CPU 进程,而是
#   先用 top 的 id/wa + D 状态进程数,把它【定性】:
#   到底是 CPU 不够,还是 IO 卡住。方向错了,后面
#   全白费。

修复 3:IO 型高负载——揪出那块被打满的磁盘

# === ★ 确认是 IO 型后:定位是哪块盘、被谁打满 ===

# === 第一步:iostat 看每块磁盘的繁忙度 ===
# iostat 在 sysstat 包里,没有就 yum install sysstat。
$ iostat -x 1 3
# -x 详细信息,1 秒一次,共 3 次。重点看这几列:
Device  r/s    w/s    rkB/s   wkB/s  await  %util
vda     2.0    5.0    32.0    80.0   1.2    0.8
vdb     0.0    880.0  0.0    112000  420.0  99.7
#                                    ^^^^^  ^^^^^
# ★ %util:这块盘有百分之多少的时间在忙。99.7% =
#   几乎一刻不停 —— 这块盘【就是瓶颈】。
# ★ await:平均每个 IO 请求耗时(毫秒)。420ms!
#   正常机械盘几毫秒、SSD 不到 1ms —— 420ms 是被
#   严重排队拖出来的。
# ★ vdb 这块盘被打满了,vda 没事。

# === ★ 第二步:谁在打这块盘 —— pidstat 看进程级 IO ===
$ pidstat -d 1 3
# -d 显示每个进程的磁盘 IO:
   UID  PID    kB_rd/s   kB_wr/s   Command
   27   12011  0.00      98000.0   mysqld
   1000 12044  0.00      8000.0    java
#                         ^^^^^^^ ★ mysqld 在疯狂写盘
# ★ 一眼看出:是 mysqld 在往 vdb 上猛写 —— 顺着它查
#   下去(是不是有个大查询在落临时文件?是不是
#   binlog/慢日志爆了?是不是有人在导数据?)。

# === ★ 第三步:看某个 D 进程到底卡在哪个内核调用 ===
# 想知道一个 D 状态进程具体卡在什么操作上:
$ cat /proc/12011/stack
[<0>] io_schedule+0x12/0x40
[<0>] wait_on_page_bit+0x...        # ★ 卡在等一个磁盘页
[<0>] ...
# ★ io_schedule / wait_on_page —— 实锤:它在等磁盘 IO。

# === 其他趁手的工具 ===
$ vmstat 1                # 看 b 列(等 IO 的进程数)、wa 列
$ iotop -oP               # ★ 像 top 一样,实时按 IO 排进程
# vmstat 的 b 列,就是当前阻塞在 IO 上的进程数,
#   和 D 状态进程数基本对应。

# === 认知 ===
# ★ IO 型高负载的排查链是固定的:iostat 找出【哪块盘】
#   被打满(%util/await)-> pidstat -d 找出【哪个进程】
#   在打它 -> 再顺着那个进程查【它为什么要做这么多 IO】。

修复 4:D 状态进程——为什么它"睡着"还推高 load

# === ★ 把 D 状态这个"反直觉"的东西彻底说清 ===

# === 进程状态回顾 ===
# ps 的 STAT 列,常见这几种:
#  R  运行 / 可运行(在 CPU 上,或排队等 CPU)
#  S  可中断睡眠(在等事件,可被信号唤醒,绝大多数
#     空闲进程都是 S)
#  D  ★ 不可中断睡眠
#  Z  僵尸(已死,等收尸)
#  T  已停止

# === ★ S 和 D 都是"睡眠",区别在哪 ===
# 都是"睡着、没在用 CPU",但:
#  - S(可中断):睡得浅。你给它发信号(比如 kill),
#    它能被【立刻唤醒】来响应。
#  - D(不可中断):★ 睡得死。它在等一个【内核级的
#    操作】完成 —— 最典型就是【等磁盘 IO】。在这个
#    操作返回之前,它【拒绝被任何信号唤醒】,连
#    kill -9 都得等它醒了才生效。

# === ★ 为什么 D 要"不可中断" ===
# 一个进程发起磁盘读,内核正在 DMA 往内存里搬数据。
#   这个过程中★ 不能被打断 —— 否则数据搬一半、缓冲区
#   状态错乱,会出大乱子。所以内核让它进 D 状态:
#   "别吵,等这个底层操作干净地完成"。
# ★ 正常情况下,IO 几毫秒就完事,D 状态一闪而过。

# === ★ 问题出在 IO 变慢的时候 ===
# 一旦磁盘被打满、或存储出故障(NFS 卡死、磁盘坏道),
#   IO 迟迟不返回 —— 进程就【长时间卡在 D 状态】。
# 而 Linux 的 load 又恰恰把 D 状态算进去。于是:
#  慢 IO -> 一大批进程长期 D -> load 被一路顶高。
# ★ 这些进程一个 CPU 周期都没用 —— load 高,CPU 闲,
#   矛盾就这么来的。

# === ★ D 状态进程,kill 通常杀不动 ===
$ kill -9 12011
$ ps -p 12011 -o stat        # 多半还是 D
# ★ 它在等 IO,信号送不进去。想让它解脱,只有两条路:
#  1. 等那个慢 IO 完成 / 超时(磁盘恢复了它自然就醒)。
#  2. 从【根上解决 IO 慢】—— 见修复 5。
# ★ 对 D 状态进程本身使劲是没用的,要去治那个慢 IO。

# === 一条命令看清 D 进程在等谁 ===
$ for p in $(ps -eo pid,stat | awk '$2 ~ /D/ {print $1}'); do
    echo "=== PID $p ==="; cat /proc/$p/stack 2>/dev/null | head -3
  done
# ★ 把每个 D 进程的内核栈顶打出来,基本都指向 IO。

# === 认知 ===
# ★ D 状态是理解"load 高 CPU 闲"的钥匙:进程睡着、
#   不耗 CPU,却照样算进 load。看到一堆 D,就别再
#   盯着 CPU 了 —— 去治 IO。

修复 5:正确解法——按类型对症,把 load 降下去

# === ★ 解法:先定性,再分两条路对症下药 ===

# === ★ 解法 1:IO 型高负载(本文这次)怎么治 ===
# 思路:不是加 CPU,是【减少 / 加速磁盘 IO】。
# (1) 揪出狂打 IO 的进程,从源头掐:
$ pidstat -d 1                       # 找到元凶进程
#   - 是某个大查询/全表扫描 -> 优化 SQL、加索引
#   - 是日志疯狂刷盘        -> 降日志级别、异步写
#   - 是有人在 scp/导数据   -> 错峰、限速(用 ionice)
$ ionice -c3 -p 12044                # ★ 把某进程 IO 优先级降到空闲级
# (2) 磁盘本身扛不住 -> 换更快的盘(SSD)、上 RAID、
#     或把热数据分到不同盘。
# (3) 用 page cache:很多重复读,内存够的话会被
#     缓存,加内存能显著减少实际磁盘读。

# === ★ 解法 2:CPU 型高负载怎么治 ===
# 如果 top 显示 id 低、us/sy 高、进程几乎全是 R:
$ top                                # 按 P 排序,找吃 CPU 的进程
$ pidstat -u 1                       # 进程级 CPU 占用
#   - 某进程死循环/算法烂 -> 改代码、优化算法
#   - 真的是流量大、活儿多 -> 加 CPU 核、加机器、
#     做负载均衡把流量分摊出去
# ★ CPU 型,核心是"要么让活儿变少/变快,要么加算力"。

# === ★ 解法 3:别再"看见高 load 就重启" ===
# 我以前的下意识反应是重启服务/机器。重启确实能让
#   load 暂时归零 —— 但★ 它只是把卡住的进程全清了,
#   【病根(慢磁盘 / 烂 SQL)一点没动】。过会儿
#   load 照样涨回来。
# ★ 重启是"清现场",不是"治病"。一定要定位到
#   那个根因(哪块盘、哪个进程、为什么),改掉它。

# === ★ 解法 4:配监控,别等 load 高了才看 ===
# 监控 load 时,★ 务必同时采集这几个指标,否则光看
#   load 一个数,根本不知道是 CPU 还是 IO:
#  - load average(且要除以核数看)
#  - CPU 的 us / sy / id / wa
#  - 磁盘的 %util / await
#  - D 状态进程数
# ★ 这几个一起看,load 一高,立刻能定性。

# === ★ 解法 5:给排查留个"快照脚本" ===
# load 告警常常来得快去得快,等你 SSH 上去现场没了。
#   写个脚本,告警时自动抓一份现场:
#!/bin/bash
{ date; uptime
  echo '--- cpu ---';  top -bn1 | head -5
  echo '--- D 进程 ---'; ps -eo pid,stat,comm | awk '$2~/D/'
  echo '--- iostat ---'; iostat -x 1 2
} >> /var/log/load_snapshot.log
# ★ 让监控在 load 超阈值时自动跑它 —— 现场就留住了。

# === 验证 ===
$ uptime                             # load 降回 核数 以下
$ ps -eo stat | grep -c '^D'         # D 状态进程回落到个位数
$ iostat -x 1 3                      # %util 不再贴着 100%
# ★ 三个一起回归正常,才算这次 load 高真的根治。

修复 6:负载排查纪律

# === 这次事故暴露的认知盲区,定几条纪律 ===

# === 1. ★ load average 不是 CPU 使用率,是"R + D 状态进程数" ===

# === 2. ★ load 高先除以核数看:load/核数 > 1 才算真排队 ===
$ echo "load=$(cut -d' ' -f1 /proc/loadavg) cores=$(nproc)"

# === 3. ★ load 高先定性:看 top 的 id/wa,数 D 状态进程 ===
$ ps -eo stat | grep -c '^D'

# === 4. id 高 + 一堆 D 状态进程 = IO 型高负载,CPU 没问题 ===

# === 5. ★ IO 型:iostat 找被打满的盘(%util/await),pidstat -d 找元凶进程 ===

# === 6. ★ D 状态进程在等 IO,不耗 CPU 却算进 load,kill 也杀不动 ===

# === 7. id 低 + us/sy 高 + 进程全是 R = CPU 型,去抓吃 CPU 的进程 ===

# === 8. ★ 别"看见高 load 就重启",重启只清现场,病根还在 ===

# === 9. 监控 load 要同时采集 CPU us/sy/id/wa、磁盘 %util、D 进程数 ===

# === 10. 排查"load 高"的步骤链 ===
$ uptime                          # ① load 多少,除以核数
$ top                             # ② 看 id 高还是低、wa 有没有值
$ ps -eo stat | grep -c '^D'      # ③ 数 D 状态进程 -> 定性
$ IO型 -> iostat + pidstat -d     # ④ 找盘、找元凶进程
$ CPU型 -> top 按 CPU + pidstat -u # ④ 找吃 CPU 的进程
# 按这个顺序,"load 高"基本能定性、能定位、能根治。

命令速查

需求                        命令
=============================================================
看 load average             uptime  或  cat /proc/loadavg
看 CPU 核数                  nproc
看 CPU 各项占比 + iowait     top (看 us/sy/id/wa 那一行)
统计各状态进程数            ps -eo stat | awk '{print substr($1,1,1)}' | sort | uniq -c
数 D 状态进程               ps -eo stat | grep -c '^D'
挑出 D 状态进程             ps -eo pid,stat,comm | awk '$2 ~ /D/'
看磁盘繁忙度 %util await    iostat -x 1 3
看进程级磁盘 IO             pidstat -d 1
看进程级 CPU 占用           pidstat -u 1
实时按 IO 排进程            iotop -oP
看 D 进程卡在哪个内核调用   cat /proc//stack
看阻塞 IO 的进程数          vmstat 1 (看 b 列和 wa 列)
降某进程的 IO 优先级        ionice -c3 -p 

口诀:load 不是 CPU 使用率,数的是 R 加 D 状态进程数,D 状态是等 IO 的睡眠进程
      load 高先除核数再看 top 的 id,id 高加一堆 D 就是 IO 型,去 iostat 找被打满的盘

避坑清单

  1. load average 不是 CPU 使用率,它数的是系统里 R 运行可运行和 D 不可中断睡眠状态的进程数量
  2. D 状态进程在等磁盘 IO,它睡着没在用 CPU,却照样被算进 load,这就是 load 高 CPU 闲的根源
  3. load 的绝对值要除以 CPU 核数才有意义,load 除核数大于 1 才说明真有任务在排队等
  4. load 高先定性:看 top 的 id 高还是低、wa 有没有值,再数 D 状态进程,别一上来就抓 CPU 进程
  5. id 高加一堆 D 状态进程是 IO 型高负载,CPU 没问题,要去查磁盘;id 低 us/sy 高是 CPU 型
  6. 判断 IO 型负载更可靠的信号是 D 状态进程数量,而不是只看 iowait,wa 低不代表没有 IO 问题
  7. IO 型用 iostat -x 找 %util 贴近 100 await 很大的盘,再用 pidstat -d 找狂打 IO 的元凶进程
  8. D 状态进程在等内核级 IO 操作,拒绝被信号唤醒,kill -9 也杀不动,要去治那个慢 IO
  9. 别看见高 load 就重启,重启只是把卡住的进程清掉清现场,慢磁盘烂 SQL 的病根一点没动
  10. 监控 load 要同时采集 CPU 的 us sy id wa、磁盘的 util await、D 进程数,否则光看 load 定不了性

总结

这次"load 飙到 24、CPU 却闲着 88%"的事故,纠正了我一个用了很多年、却从来没有真正去考证过的认知。在我的脑子里,"load average"和"CPU 使用率",长久以来就是同一个东西的两种说法。我一直觉得,load 就是一根插在 CPU 上的体温计:load 低,CPU 凉快;load 高,CPU 发烧。它们俩在我的理解里是严丝合缝、同涨同落的。正因为这个等式在我心里太天经地义,所以当告警告诉我 load 是 24 时,我的大脑没有经过任何一秒的思考,就直接翻译成了一句话:CPU 被榨干了。我 SSH 上去要做的事,从一开始就被这个翻译给框死了——我要去抓那个吃满 CPU 的罪魁祸首。可 top 打开的那一刻,现实给了我一记响亮的耳光:load 是 24,CPU 的空闲却高达 88%。这两个数字摆在同一屏幕上,像是在公然嘲笑我那个等式。我的第一反应,甚至不是去怀疑我的认知,而是去怀疑工具——我觉得是 top 显示错了,是哪里出了 bug。我宁可相信是计算机在骗我,也没想过,可能是我对"load"这个词的理解,从一开始就是残缺的。复盘到根上,我才明白,我那个"load = CPU 使用率"的等式,丢掉了一整个、而且至关重要的一半。Linux 的 load average,它统计的从来不只是"在用 CPU 的进程",它统计的是"在用 CPU 的进程"加上"卡在不可中断睡眠、等着 IO 的进程"。是这后半句,我整个职业生涯里都视而不见。一个进程在等磁盘把数据读上来的时候,它会进入一种叫 D 的状态——它睡着了,它一个 CPU 周期都不消耗,可它,依然被结结实实地算进了 load 这个数字里。这就像我一直以为,一家医院的"繁忙程度",就是看有多少医生正在做手术;可我忘了,候诊大厅里那些坐着干等、等着拍片结果出来的病人,他们没有占用任何一个医生,却同样是这家医院"拥堵"的一部分。我那台服务器,CPU 就是那些闲着的医生——没什么手术可做,所以悠闲;而那 22 个卡在 D 状态的进程,就是挤满候诊大厅、苦等一台慢得要命的 X 光机(那块被打满的磁盘)的病人。医院明明很"堵",医生却很"闲",这两件事不但不矛盾,反而恰恰是同一个病因——X 光机太慢——的一体两面。我之所以会被这个现象彻底搞懵,不是因为现象本身有多诡异,而是因为我手里那把用来度量"忙"的尺子,本身就是错的。我用一把只刻着"CPU"的尺子,去量一个其实包含了"CPU"和"IO 等待"两段的长度,量出来的数我看不懂,于是我以为是世界出了问题。这次最大的收获,是我意识到,一个被我用了无数遍、张口就来的术语,我可能压根没有真正理解过它的定义。"load"这个词我敲过成千上万次,可它到底"数"的是什么,我从来没有低下头去认真看一眼。我把一个一知半解的概念,当成了一块不容置疑的基石,然后在它上面盖起了我全部的判断——而当这块基石被现实证明是歪的,盖在上面的判断,自然就全塌了。所以下一次,当某个我"早就懂了"的指标,给出一个让我无法理解的数字时,我不会再急着去怀疑工具、怀疑机器了。我会先停下来,把那个我自以为烂熟于心的术语,重新、老老实实地查一遍它的定义,问自己一句:这个数字,它到底在数什么?——很多时候,真正出故障的不是机器,而是我脑子里那张早已过时、却被我当成真理的、关于这个世界如何运转的地图。

—— 别看了 · 2026
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理 邮箱1846861578@qq.com。
Linux教程

定时任务手动能跑 cron 里不执行:一次 Linux crontab 环境排查复盘

2026-5-20 22:12:37

Linux教程

free 看内存只剩两百兆吓一跳:一次 Linux buff/cache 排查复盘

2026-5-20 22:21:22

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索