Linux vmstat 的 si 和 so 怎么判断交换抖动
来源:17golang原创
时间:2026-10-07 01:09:21 116浏览 收藏
我第一次在生产机上看到 swpd 很大时,直觉是“机器正在疯狂换页”。后来连续看了几十秒才发现,si 和 so 一直是 0:那只是一些冷页仍留在交换区,并不等于系统正在抖动。真正值得警惕的是交换流量持续发生,尤其是页面刚换出又很快被换回,同时业务延迟、任务阻塞或内存压力也在上升。
官方资料:https://man7.org/linux/man-pages/man8/vmstat.8.html、https://docs.kernel.org/accounting/psi.html
判断交换抖动没有一个适用于所有机器的固定 si/so 阈值。先用vmstat -y -w -t 1 60连续采样:如果si、so在多个采样周期反复或同时非零,并伴随b、wa、memory PSI 或业务延迟上升,就应按交换抖动排查;只有swpd非零而 si/so 长期为 0,通常不是抖动。
先分清 swpd、si 和 so 各自回答什么
vmstat 的这三个字段很容易被混在一起。swpd 是当前已经占用的交换空间,是一个存量;si 是每秒从交换设备读回内存的量,so 是每秒从内存写到交换设备的量,它们是采样周期内的流量。si、so 的显示单位受 -S 选项影响,因此跨机器比较前要先确认单位。
这也解释了一个常见现象:系统以前有过内存压力,部分长期不用的匿名页被换出,后来压力已经消失,但这些冷页没有被访问,于是 swpd 仍不为 0,si、so 却保持为 0。此时为了把 swpd 清零而直接执行 swapoff,可能反而制造新的内存风险。

用 60 秒采样避开第一行平均值
我现在排查时会先保留一分钟原始观察窗口,而不是截取单行。vmstat 手册明确说明:第一份报告是从上次开机到现在的平均值,后续报告才对应指定的采样间隔。使用 procps-ng 的 -y 可以直接省略第一份报告,-w 避免大数值挤乱列宽,-t 便于把波动与业务事件对齐。
# 每秒采样一次,共观察 60 个有效周期 vmstat -y -w -t 1 60
检查时先盯住 si 和 so 的连续性,再看同一行的 b 与 wa。单个采样点非零只能说明那个瞬间发生了换页,不能独立证明抖动。若系统里的 vmstat 不支持 -y,可以运行普通的 vmstat 1 61,人工忽略第一份数据,不要把开机以来的平均值与一秒采样混在一起。
按四种形态判断交换压力
| 观察形态 | 更可能的含义 | 判断 |
|---|---|---|
swpd > 0,si/so 长时间为 0 | 冷页留在交换区,当前没有明显交换流量 | 通常不是抖动 |
| si 或 so 偶尔出现一次,随后归零 | 进程启动、恢复访问冷页或短时内存峰值 | 继续观察,不凭单点下结论 |
| so 连续非零,si 很少,内存压力上升 | 内核正在持续回收匿名页,工作集可能逼近物理内存 | 已经有交换压力 |
| si 与 so 在多个周期反复非零,同时 b、wa 或延迟升高 | 活跃工作集在内存与交换设备之间来回搬运 | 高度怀疑交换抖动 |
这里最重要的是“持续”和“影响”。NVMe、SATA SSD、云盘和机械盘承受同样交换速率时,延迟后果可能完全不同;数据库、Java 服务和批处理任务的可接受范围也不一样。因此,与其背一个“si 超过多少就危险”的数字,不如比较同一业务的正常基线,并观察用户请求延迟或吞吐是否同步恶化。
把 b、wa 和可用内存放进同一张判断图
b 表示等待 I/O 完成而阻塞的进程数,wa 表示 CPU 等待 I/O 的时间占比。它们并不专属于交换 I/O,普通磁盘读写同样会推高这些值,所以只能作为相关证据。实际排查时,我会同时打开另一个窗口查看可用内存:
# 查看可用内存与交换区存量 free -h # 查看累计换入、换出页计数 grep -E '^(pswpin|pswpout) ' /proc/vmstat
如果 so 持续出现、可用内存处于低位、pswpout 在观察窗口内不断增长,而 b 或 wa 也同步抬升,交换正在对运行造成影响的证据就更完整。反过来,如果块设备本身繁忙但 si/so 为 0,应转向普通存储 I/O 排查,不要把所有 wa 都归因于 swap。

用 memory PSI 确认任务是否真的被内存拖住
较新的 Linux 环境通常还能读取 /proc/pressure/memory。PSI 的 some 表示至少有部分任务因内存资源受阻,full 表示所有非空闲任务同时受阻;内核文档把持续处于 full 状态的工作负载视为抖动。这个指标比“交换了多少字节”更接近用户实际感受到的停顿。
# 查看最近 10、60、300 秒的内存压力占比 cat /proc/pressure/memory
若文件不存在,说明当前内核或配置没有提供可用的 PSI 接口,继续使用 vmstat、业务延迟和累计页计数即可。若 full avg10 明显上升,并且同一时间 si/so 来回出现,这比单看 swpd 更能支持“系统正在交换抖动”的判断。
确认抖动后先处理工作集,不急着改 swappiness
真正遇到抖动时,我会先找出是谁扩大了活跃工作集,以及最近是否发生了并发、缓存、批处理或容器限额变化:
# 按常驻内存从高到低列出进程,先确认主要使用者 ps -eo pid,comm,rss,vsz --sort=-rss | head -n 15 # 只读取当前 swappiness,先留证据再决定是否调整 sysctl vm.swappiness
短期处置通常是降低并发、暂停可重试批任务、限制缓存增长,或把部分负载迁走;长期处置则是修正内存泄漏、重新估算工作集、调整容器内存上限或增加物理内存。swappiness 描述内核在交换页与文件页回收之间的相对成本偏好,并不是“禁止抖动”的开关。直接把它改成 0,既不能弥补工作集超过内存,也可能把问题推向更剧烈的直接回收或 OOM。
同样,不要在未确认可用内存足够时直接 swapoff -a。该操作需要把仍在交换区的页重新装回内存,压力已经很高时可能让故障进一步扩大。更安全的顺序是先降低工作集,确认 si/so、PSI 和业务延迟回落,再评估是否需要改配置。
常见问题
si 很高但 so 为 0,一定是交换抖动吗?
不一定。应用重新访问之前换出的冷页时,可能出现一段换入而没有同步换出。只有该现象持续、反复,并伴随任务阻塞或业务性能下降,才更接近抖动。
swpd 很大但 si 和 so 都是 0,需要清理吗?
通常不需要仅为了数值好看而清理。它说明有页留在交换区,但当前没有明显搬运。应优先关注可用内存、业务表现和后续采样趋势。
只有 so 持续非零说明什么?
这说明系统正在持续把页换出,已经存在内存回收压力,但不一定已经形成来回换页。继续观察 si 是否随后升高,并结合 PSI、b、wa 和业务延迟判断影响。
vmstat 的 si、so 能直接和两台机器比较吗?
不能只比数字。先统一 -S 单位,再考虑物理内存规模、交换介质速度、采样间隔和工作负载。更可靠的是在同一主机上与正常时段基线比较。
-
345 收藏
-
392 收藏
-
Golang · Go教程 | 3个月前 | channel · select · Context · Go教程 · 性能排查 · select channel context default time.Ticker Go教程 CPU飙高 for select459 收藏
-
395 收藏
-
Golang · Go教程 | 2个月前 | golang · Timer · 并发编程 · time.After · 性能排查 · time.After go timer Go 1.23 NewTimer Timer.Reset Timer.Stop403 收藏
-
258 收藏
-
268 收藏
-
294 收藏
-
483 收藏
-
455 收藏
-
181 收藏
-
439 收藏
-
321 收藏
-
294 收藏
-
233 收藏
-
166 收藏
-
426 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习