Linux内存管理实战:OOM Killer排查与Swap交换分区调优

Linux内存管理中,进程无故消失、服务深夜自动重启、系统响应突然卡死,三类故障十有八九指向内存问题。内核在物理内存耗尽时触发OOM Killer强制回收,Swap配置不当会让整机性能雪崩。排查这类故障需要理解free输出的真实含义、OOM Killer的评分规则和Swap的换页机制,三块内容串起来,内存类故障基本可以闭环。

free命令输出解读:available才是可用内存

free -m的输出常被误读。buff/cache列显示几个GB的占用,看起来内存快用完了,实际上这部分是页缓存,进程需要内存时内核会自动回收。判断内存是否紧张只看available列,它表示不需要回收缓存就能直接分配的量。用psmph工具做验证:

$ free -m
              total   used   free   buff/cache   available
Mem:          7822   3411    210         4200         3998
Swap:          511    302    209

available接近4GB说明内存健康。available低于总量的10%且swap used持续上涨,才需要介入。另一个常用判断是sar -B的pgscan/s列,每秒扫描页数持续大于0说明内存回收压力大,是内存不足的前兆信号。

OOM Killer触发机制与日志定位

物理内存和Swap都耗尽时,内核调用out_of_memory函数,按oom_score选 victim。oom_score计算依据是进程实际占用内存加上swap占用,数值范围0到1000,分数越高越先被杀。排查入口在内核日志:

$ dmesg -T | grep -i "killed process"
[Mon Sep 14 03:17:22 2026] Out of memory: Killed process 18342 (java) 
total-vm:32gB, anon-rss:6.2GB, file-rss:0, pgtables:13632kB

$ journalctl -k --since "1 hour ago" | grep -i oom

日志里三个数字各有用途:total-vm是虚拟地址空间大小,anon-rss才是实际物理占用,被杀时java进程占了6.2GB物理内存。结合oom_score_adj可以反推当时系统整体水位:受保护进程少、可回收缓存少,OOM才会真正触发。只看进程占用不够,需要同步检查当时是否有突发流量,常见误因是某个定时任务在同一时间点批量拉起。

oom_score_adj调整:保护关键进程不被误杀

关键服务需要显式降低OOM评分,方法是写/proc/PID/oom_score_adj,取值-1000到1000,-1000表示完全豁免:

# MySQL主库进程豁免OOM
echo -1000 > /proc/$(pidof mysqld)/oom_score_adj

# systemd管理的服务写入unit文件永久生效
[Service]
OOMScoreAdjust=-900
OOMPolicy=continue

豁免要有节制。把所有服务都设为不可杀,OOM Killer最后会选中内核线程甚至直接panic整机。正确做法是只保护数据库主进程和sshd,其他进程留给内核裁决。重启后设置丢失,systemd unit里配置OOMScoreAdjust是唯一可靠途径。反向场景同样存在:测试用的压测进程设为500,内存紧张时最先被杀,避免它拖垮生产服务。

Swap交换分区大小与swappiness参数调优

swappiness控制内核换出匿名页的倾向,取值0到200,默认60。值越高越积极使用Swap,值越低越倾向回收页缓存。数据库服务器建议10,应用服务器20到30,纯计算节点可以考虑1。大于100的值表示允许Swap优先于缓存回收,极少使用。修改方法:

$ sysctl vm.swappiness=10
$ echo "vm.swappiness=10" >> /etc/sysctl.conf

# 查看每个进程的实际换页量,确认调优效果
$ for f in /proc/*/status; do 
    awk '/^Name|^VmSwap/{printf $2 " " $3 "KB
"}' $f 2>/dev/null
  done | sort -k2 -rn | head

Swap大小不是越大越好。云服务器常见配置误区是Swap开到内存的两倍,冷数据全量换出后,一旦进程被调度到,从磁盘换回的延迟以百毫秒计,表现为整机卡顿。8GB内存的云主机Swap给2到4GB足够,优先作用是给内核留出缓冲时间处理突发,而不是长期存储冷数据。Swap所在的磁盘顺序写性能决定换页速度,机械盘上vmstat的si/so两列持续大于100KB/s时,业务延迟已经受损,这时候要么加内存,要么查Swap大户。

内存泄漏排查:smem与valgrind定位方法

排查内存泄漏分两步,先定位进程,再定位代码。进程级用smem按PSS排序,PSS是按共享比例分摊后的实际占用,比RSS准确:

$ smem -r -k -t | head -15
# 或按增量监控,间隔采集对比
$ while true; do 
    date; grep VmRSS /proc/$(pidof worker)/status; sleep 300
  done | tee mem_trend.log

PSS曲线每24小时上涨500MB且无回落,基本判定泄漏。C/C++程序用valgrind –leak-check=full跑一遍用例集,输出直接给出泄漏调用栈。Java程序用jmap -histo:live | head -20看对象排行,配合jcmd GC.heap_dump导出快照,MAT工具分析dominator tree。Go程序内置pprof,curl http://host/debug/pprof/heap拉取堆画像,inuse_space按来源聚合能直接看到泄漏点。长周期泄漏进程上线定时重启是止血手段,根因修复后记得撤销。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/linux-nei-cun-guan-li-shi-zhan-oomkiller-pai-cha-yu-swap/

(0)
小编小编
上一篇 7小时前
下一篇 7小时前

相关推荐