Linux系统频繁出现内存耗尽问题会直接影响业务服务的可用性,严重时会导致进程被OOM机制杀死,甚至系统出现卡死无响应的情况。要解决这个问题,需要从排查定位到优化调整逐步推进。
第一步:排查当前内存使用情况
首先需要通过系统自带工具查看内存的整体使用状态,确认是否存在真实的内存不足,还是缓存占用的误判。
常用内存查看命令
使用free命令可以快速查看内存的整体使用概况:
# 以人类可读的格式显示内存信息 free -h
输出结果中需要重点关注几个指标:total是总内存,used是已使用内存,free是完全空闲内存,buff/cache是缓冲和缓存占用的内存,available是系统可提供给新进程使用的内存,这个值才是判断内存是否充足的核心指标。
如果需要查看具体进程的内存占用情况,可以使用top或者htop命令,按内存占用排序找到占用最高的进程:
# 运行top命令后按Shift+M按内存占用降序排序 top
第二步:定位内存耗尽的根因
找到内存占用高的进程后,需要进一步分析该进程的内存使用是否合理,常见的原因有以下几种:
- 应用存在内存泄漏,随着运行时间增长内存占用持续上升
- 系统缓存参数配置不合理,导致缓存占用过多无法释放
- 同时运行的进程过多,总内存需求超过系统物理内存上限
- 内核参数配置异常,导致内存回收机制无法正常工作
排查内存泄漏的方法
如果是自研应用出现内存泄漏,可以通过对应语言的调试工具分析,比如Java应用可以使用jmap导出堆内存快照,用MAT工具分析;C/C++应用可以使用valgrind工具检测内存泄漏:
# 检测指定进程的内存泄漏情况,pid替换为实际进程ID valgrind --leak-check=full -v /proc/pid/exe pid
第三步:针对性优化解决
根据定位到的根因,选择对应的优化方案:
应用层优化
如果是应用本身的问题,需要修复内存泄漏的代码,或者调整应用的内存配置,比如Java应用可以合理调整JVM的堆内存大小,避免堆内存设置过大超过系统承载能力:
# 启动Java应用时设置初始堆内存和最大堆内存 java -Xms2g -Xmx4g -jar your_app.jar
系统层优化
如果是系统缓存或者内核参数的问题,可以调整以下内核参数优化内存回收机制:
| 参数名称 | 作用说明 | 推荐配置值 |
|---|---|---|
| vm.swappiness | 控制内存不足时使用交换分区的倾向,值越高越倾向使用交换分区 | 10-30 |
| vm.overcommit_memory | 控制内存分配策略,0是启发式分配,1是允许超额分配,2是禁止超额分配 | 0或2 |
| vm.drop_caches | 手动释放缓存,写入1释放页缓存,2释放目录项缓存,3释放所有缓存 | 临时释放时写入3 |
修改内核参数可以通过sysctl命令临时生效,也可以写入配置文件永久生效:
# 临时修改swappiness参数 sysctl -w vm.swappiness=20 # 永久修改,写入/etc/sysctl.conf文件 echo "vm.swappiness=20" >> /etc/sysctl.conf sysctl -p
硬件扩容
如果经过优化后内存仍然不足,说明当前业务的内存需求已经超过现有物理内存上限,此时需要增加物理内存,或者将部分服务迁移到其他服务器,分散内存压力。
长期监控预防
解决当前的内存耗尽问题后,还需要建立长期的内存监控机制,避免问题再次出现。可以使用prometheus搭配node_exporter采集内存指标,设置告警阈值,当内存使用率超过80%时及时通知运维人员排查。同时定期巡检系统内存使用情况,及时发现潜在的内存泄漏问题。