如何处理Linux系统中频繁出现的内存使用率过高问题

来源:Java编程网作者:清原小日向头衔:网络博主
导读:本期聚焦于小伙伴创作的《如何处理Linux系统中频繁出现的内存使用率过高问题》,敬请观看详情。一台跑了半年的生产服务器突然开始每隔几小时就告警内存使用率超过九成,重启后短暂恢复又反复飙升,这种情形往往不是物理内存真的不够用。Linux 的空闲内存会被内核自动用作页缓存以提升磁盘读写效率,因此单纯看 used 指标容易产生误判。真正需要关注的是不可回收的匿名页与 slab 占用是否持续增长。通过 smem 观察进程实际常驻内存,结合 /proc/meminfo 里的 SReclaimable 与 SUnreclaim 字段,可以区分缓存与泄漏。本文梳理从指标误读到进程级定位的完整路径,并给出限制服务内存、调整 swap 与 drop cache 策略等实操手段,帮助运维人员在不盲目扩容的前提下稳住系统。

Linux 服务器线上运行一段时间后,监控面板里的内存使用率曲线频繁冲高,往往让运维人员第一时间想到加内存或重启。但多数情况下,这种“过高”只是内核利用空闲内存做缓存的正常机制,或者是某个长期运行的服务在缓慢泄漏。只有搞清楚内存都去哪儿了,才能对症下药。

如何处理Linux系统中频繁出现的内存使用率过高问题

一、先看清内存统计的真实含义

很多人习惯用 free -h 命令看内存,但默认输出里的 used 包含了页缓存(page cache),而这部分在内核需要时会立刻释放给应用。因此 used 高并不代表内存紧张。更合理的做法是直接读取 /proc/meminfo,关注 MemAvailable 以及 SReclaimable、SUnreclaim 等字段。

页缓存用于加速文件读写,属于可回收内存;slab 中的 SReclaimable 是目录项、索引节点等可回收内核对象,SUnreclaim 则是不可回收部分,若它持续上涨通常暗示内核级泄漏或驱动问题。用户态进程的匿名内存对应 AnonPages,这部分才是真正挤占可用内存的来源。

# 查看关键内存指标
cat /proc/meminfo | grep -E "MemTotal|MemFree|MemAvailable|Buffers|Cached|SReclaimable|SUnreclaim|AnonPages"
# 输出示例
# MemTotal:       16384000 kB
# MemFree:          512000 kB
# MemAvailable:    8200000 kB
# Cached:          6000000 kB
# SReclaimable:     800000 kB
# SUnreclaim:       350000 kB
# AnonPages:       7000000 kB

二、用工具定位是哪个进程在吃内存

传统 top 命令的 RES 列显示常驻内存,但无法区分共享内存的重复计算。更推荐 smem,它能按比例分摊共享内存,给出更准确的 PSS(按比例占用物理内存大小)。安装后执行 smem -s pss -r | head 即可看到排在前面的进程。

如果发现某个 Java 或 Python 服务 PSS 每隔几天就翻一倍,而业务量并没有增长,那大概率是堆外内存泄漏或缓存未设上限。此时可进一步用 pmap -x 进程号 查看内存映射,寻找异常大的匿名段。对于支持 Native Memory Tracking 的 JVM,还可开启对应参数做细分。

# 安装并查看进程实际物理内存占用排行
sudo apt install smem
smem -s pss -r | head -n 10

# 查看某进程的内存映射分布
pmap -x 1234 | tail -n 20

三、常见原因与对应处理方案

第一类是应用层缓存无限增长。比如自研服务用 HashMap 做本地缓存却忘了淘汰策略,解决方法是引入 LRU 或 TTL,或者改用 Caffeine、Redis 等带边界的组件。第二类是内存泄漏,需要借助 Valgrind、AddressSanitizer 或语言自带的剖析器定位未释放对象。

第三类是系统层面 swap 被禁用或过小,导致匿名页无法换出,一旦突发分配就直接 OOM。可适当开启 swap 并调整 swappiness(如设为 10)让系统更积极回收页缓存而非杀进程。第四类是内核模块或文件系统缓存不释放,可周期性执行 echo 2 > /proc/sys/vm/drop_caches 仅回收 slab 可回收部分,但生产环境需评估对 IO 的影响。

现象可能原因处理手段
MemAvailable 低,AnonPages 高用户态进程占用多限制服务内存、排查泄漏
SUnreclaim 持续增长内核/驱动泄漏更新驱动、重启节点
Cached 高但可用少脏页或 pinned 缓存调整 drop_caches、写回策略

四、建立长效防控机制

单靠人工排查不能杜绝问题。建议在监控系统中除采集 used 外,重点绘制 MemAvailable、SUnreclaim、主要进程 PSS 的时序图,并设置基于趋势的预警而非绝对值。例如当 SUnreclaim 周环比增长超百分之三十即告警。

同时,对关键服务配置 cgroup 内存上限,避免单点拖垮整机。使用 systemd 的服务可在单元文件里写 MemoryMax=2G,超限额后被杀死而非挤占别人。配合定期的堆栈与内存剖析任务,能把大部分“频繁过高”消灭在萌芽阶段。

# /etc/systemd/system/myapp.service 片段
[Service]
ExecStart=/usr/bin/python3 /opt/myapp/main.py
MemoryMax=2G
MemoryHigh=1.5G

五、应急操作清单

当线上已经告警且需要快速缓解,可依次执行:确认是否误报(看 MemAvailable)、找出 top PSS 进程、对非核心服务重启、临时放宽 swap 策略、必要时手动回收 slab。切忌一上来就 reboot,那样会丢失现场导致无法根因分析。

下面给出一个简易排查脚本,适合放进定时任务做粗筛,发现异常再人工介入。它只做数据抓取,不自动处理,降低误操作风险。

#!/bin/bash
# 简易内存异常记录脚本
ts=$(date '+%F %T')
avail=$(grep MemAvailable /proc/meminfo | awk '{print $2}')
sunreclaim=$(grep SUnreclaim /proc/meminfo | awk '{print $2}')
if [ "$avail" -lt 1048576 ]; then
  echo "$ts WARN avail=${avail}KB sunreclaim=${sunreclaim}KB" >> /var/log/mem_check.log
fi

通过上述分层方法与工具组合,Linux 内存使用率频繁过高的问题通常能在不增加硬件成本的前提下被理清并稳定控制。核心始终是区分缓存与真实占用,以及把排查动作常态化。

Linux内存管理内存泄漏排查系统性能优化修改时间:2026-08-05 01:15:32

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。