Linux服务器Cache占用过多内存导致系统内存不足最终java应用程序崩溃解决方案

问题描述

Linux内存使用量超过阈值,使得Java应用程序无可用内存,最终导致程序崩溃。即使在程序没有挂掉时把程序停掉,系统内存也不会被释放。


找原因的过程

这个问题已经困扰我好几个月了,分析过好多次都没有找到原因,网上查了一下该问题其他人也都遇到过,不过并没有什么好的解决方案,因为项目一直没有上线,每次当内存不足时导致程序崩溃都是重启服务就好了,索性也就没花太多的时间来找问题。现在项目马上上线了,不能在出现程序崩溃的情况了,况且还是前置系统,更不能出现任何问题。

最开始一直认为是程序的原因导致内存泄漏,使用jdk自带的jmap -F -dump:live,format=b,file=/usr/local/sztFront/logs/heapdump.bin命令输出过几次dump文件,通过MemoryAnalyzer分析,应用程序没有耗内存过大的变量。后台猜测是否日志输出过多导致的,毕竟是前置系统,每天的报文量特别大,日志能到达5,6个G。所以把日志接收报文关了,日志大小马上降下来了,每天200M。程序挂掉的时间变长了,原来差不多一周就挂掉了,现在可以达到两周左右才挂掉,还是不行,没有冲根本上解决问题。经过在网上搜索各种相关的问题,问题出现在Cached的值过大,导致系统没有可以再分配的内存空间。Cached只要用来缓存文件的,经常读写的文件会被缓存到Cached中,可以增加读写效率,该功能是Linux系统内核提供的,从2.6.16以后的核心版本才提供,也就是老版的操作系统,如红旗DC 5.0、RHEL 4.x之前的版本都没有这就可以解释为什么我的项目总挂掉了,我的项目主要就是处理文件的,所以接收和下载的文件会被缓存起来,一直耗着内存不释放,即使把程序停掉也不会释放内存。最后找到了三条执行,可以清理cached的内存

三条指令:

sync

echo 1 > /proc/sys/vm/drop_caches
echo 2 > /proc/sys/vm/drop_caches
echo 3 > /proc/sys/vm/drop_caches

执行完这三条指令后通过free -m命令查看,free可用内存马上增多,buff/cache列值变小,说明内存被释放了,但是不能总是手动的执行这三条指令,所以最后写了一个shell脚本,开启Linux定时任务crond,每天早上检查一次free内存,当小于4G时执行这三条命令(注:系统内容20G)。

注意:在执行这三条命令之前一定要先执行sync命令(描述:sync 命令运行 sync 子例程。如果必须停止系统,则运行sync 命令以确保文件系统的完整性。sync 命令将所有未写的系统缓冲区写到磁盘中,包含已修改的 i-Node、已延迟的块 I/O 和读写映射文件


解决方案(手动)

1. 修改/proc/sys/vm/drop_caches,释放Slab占用的cache内存空间(参考drop_caches的官方文档):

Writing to this will cause the kernel to drop clean caches, dentries and inodes from memory, causing that memory to become free.
To free pagecache:
* echo 1 > /proc/sys/vm/drop_caches
To free dentries and inodes:
* echo 2 > /proc/sys/vm/drop_caches
To free pagecache, dentries and inodes:
* echo 3 > /proc/sys/vm/drop_caches
As this is a non-destructive operation, and dirty objects are notfreeable, the user should run "sync" first in order to make sure allcached objects are freed.
This tunable was added in 2.6.16.

注意:在执行这三条命令前先执行sync命令


解决方案(自动)

1、编写shell定时任务脚本freemem.sh

#! /bin/sh
used=`free -m | awk 'NR==2' | awk '{print $3}'`
free=`free -m | awk 'NR==2' | awk '{print $4}'`
echo "===========================" >> /app/memory/logs/mem.log
date >> /app/memory/logs/mem.log
echo "Memory usage before | [Use:${used}MB][Free:${free}MB]" >> /app/memory/logs/mem.log
if [ $free -le 4000 ] ; then
                sync && echo 1 > /proc/sys/vm/drop_caches
                sync && echo 2 > /proc/sys/vm/drop_caches
                sync && echo 3 > /proc/sys/vm/drop_caches
				used_ok=`free -m | awk 'NR==2' | awk '{print $3}'`
				free_ok=`free -m | awk 'NR==2' | awk '{print $4}'`
				echo "Memory usage after | [Use:${used_ok}MB][Free:${free_ok}MB]" >> /app/memory/logs/mem.log
                echo "OK" >> /app/memory/logs/mem.log
else
                echo "Not required" >> /app/memory/logs/mem.log
fi
exit 1

2、使用crontab -e命令编辑当前用户的crontab

0 6 * * * /usr/local/tomcat/sztFileFront/bin/freemem.sh

定时任务编写参考:http://www.jb51.net/article/15008.htm


3、重启crond服务

/sbin/service crond restart

4、查看crond服务是否重启成功

/sbin/service crond status



最后,问题解决。我设定的定时任务是每天早上6点执行一次freemem.sh脚本。













<think>好的,我现在需要回答用户关于Linux内存使用百分比达到多少比较危险的问题。首先,我需要理解用户的需求,他们可能是在管理服务器或自己的计算机,遇到内存不足的情况,想知道什么时候应该警惕或者采取行动。 首先,我应该回顾一下Linux内存管理的基本机制。Linux系统会尽可能利用空闲内存来缓存磁盘数据,以提高性能,因此即使内存使用显示很高,也不一定意味着有问题。这部分缓存(cache和buffer)在需要时会被释放,供应用程序使用。所以,用户可能看到内存使用百分比很高,但实际上系统运行正常,因为缓存占用了大部分内存。 接下来,用户问的是“达到百分之多少比较危险”,这里的危险可能指的是系统开始出现性能问题,如响应变慢、应用程序崩溃,或者触发OOM Killer杀死进程。因此,我需要确定内存使用达到多少百分比时,系统可能面临这些风险。 需要考虑的几个关键点: 1. **内存使用组成**:包括应用程序使用的内存(used)和缓存/缓冲(cache/buffer)。真正的危险在于应用程序内存耗尽,而不仅仅是缓存占用高。 2. **Swap使用情况**:当物理内存不足时,系统会使用Swap空间,但频繁的Swap交换会导致性能下降。如果Swap使用率过高,也是一个危险信号。 3. **OOM Killer机制**:当内存严重不足时,Linux会触发OOM Killer,选择并终止进程以释放内存。这种情况通常发生在可用内存(包括缓存)几乎耗尽的时候。 因此,单纯的内存百分比并不能完全反映危险程度,需要结合其他因素。例如,如果内存使用率(包括缓存)达到90%以上,但大部分是缓存,可能并不危险;但如果应用程序内存占用高,且Swap使用开始增加,即使总内存使用率是80%,也可能有问题。 接下来,我需要解释如何正确评估内存状态,而不仅仅是看百分比。比如使用`free -h`命令查看内存情况,关注available字段,而不是used。当available内存非常低时,系统可能面临压力。 另外,需要提到一些具体的指标或阈值。例如,当可用内存(available)低于10%或某个具体数值(如100MB)时,系统可能开始出现性能问题。此外,Swap的使用率如果超过50%或增长迅速,也是一个警告信号。 还需要讨论不同应用场景下的差异。例如,对于数据库服务器,高内存使用是正常的,因为它们会尽量利用内存缓存数据。而对于普通应用服务器,可能需要更谨慎。 最后,应该给出建议,如监控工具(top, htop, vmstat),如何调整系统配置(如Swappiness参数),以及处理内存不足的方法(如优化应用程序、增加内存或排查内存泄漏)。 总结来说,回答需要强调不能只看单一百分比,而应综合多个因素,并提供具体的检查方法和应对策略。</think>### **Linux内存使用安全阈值解析与应对策略** --- #### **一、核心判断逻辑:不依赖单一百分比,需综合分析** Linux内存管理机制独特,**高内存占用不一定是问题**(系统会主动利用空闲内存作缓存),关键在于**可用内存(Available)**和**交换空间(Swap)**的使用情况。以下是关键指标与风险阈值: | **指标** | **安全范围** | **风险阈值** | **紧急阈值** | |--------------------|--------------------------|---------------------------------|---------------------------------| | **可用内存** | >20%总内存 | <10%总内存或<1GB | <100MB | | **Swap使用率** | <30% | 30%~70%且持续增长 | >70%且Swap频繁读写 | | **OOM Killer触发** | 未激活 | 系统日志出现`Out of memory`记录 | 进程被强制终止 | --- #### **二、风险场景与诊断方法** ##### **1. 假性内存不足(低风险)** - **现象**: `free -h`显示**Used接近90%**,但**Available充足**(如总内存32GB,Available>6GB) - **原因**: Linux主动用内存缓存磁盘数据(`buff/cache`),这部分可快速释放 - **应对**:无需处理,系统运行正常 ##### **2. 真实内存压力(中高风险)** - **现象**: - `Available < 10%`且持续下降 - `Swap使用率 > 30%`并持续增长 - `vmstat 1`显示`si`(Swap In)、`so`(Swap Out)频繁波动 - **风险**: 应用响应延迟,数据库查询变慢,可能触发OOM Killer - **诊断命令**: ```bash # 查看内存详情(重点关注Available) free -h # 监控Swap活动 vmstat 1 | grep -E 'si|so' # 按进程排序内存占用 top -o %MEM ``` ##### **3. 内存耗尽危机(紧急)** - **现象**: - `Available < 100MB` - `dmesg`日志出现`Out of memory: Kill process` - 系统频繁卡死或无响应 - **紧急处理**: - 立即终止非关键进程:`kill -9 <PID>` - 临时增加Swap空间: ```bash dd if=/dev/zero of=/swapfile bs=1G count=4 # 创建4GB文件 mkswap /swapfile && swapon /swapfile # 启用Swap ``` --- #### **三、配置优化与长期解决方案** ##### **1. 调整Swappiness(减少Swap依赖)** - **适用场景**:物理内存充足但Swap使用频繁 - **修改方法**: ```bash # 临时生效(推荐值:10~60,默认60) sysctl vm.swappiness=30 # 永久生效 echo "vm.swappiness=30" >> /etc/sysctl.conf ``` ##### **2. 限制进程内存(防止单个进程耗尽资源)** - **使用cgroups**: ```bash # 创建内存限制组(限制500MB) cgcreate -g memory:/limit_group echo "500000000" > /sys/fs/cgroup/memory/limit_group/memory.limit_in_bytes # 运行受控进程 cgexec -g memory:limit_group /path/to/process ``` ##### **3. 内存泄漏排查** - **工具链**: - `valgrind --tool=memcheck`(开发环境) - `pmap -x <PID>`查看进程内存映射 - `smem -p -s swap`统计进程Swap占用 --- #### **四、不同应用场景的参考阈值** | **场景类型** | **内存使用安全阈值** | **重点关注指标** | |--------------------|-----------------------------|-------------------------------| | 数据库服务器 | Used ≤85% + Available ≥15% | 缓存命中率、Swap活动 | | Web应用服务器 | Used ≤75% + Available ≥25% | 线程数、Java内存(如有JVM) | | 科学计算节点 | Used ≤95% + Swap ≤20% | 进程内存锁(mlock)使用情况 | | 容器/K8s节点 | Available ≥10%总内存 | 容器内存限制(cgroup) | --- #### **五、监控告警推荐配置** - **Prometheus + Grafana**: ```yaml # alert.rules - alert: HighMemoryUsage expr: (1 - (node_memory_Available_bytes / node_memory_MemTotal_bytes)) > 0.9 for: 5m labels: severity: critical annotations: summary: "内存使用超过90%(可用内存不足)" ``` - **Zabbix触发器**: ```text {Template OS Linux:system.swap.size[,pused].avg(5m)}>70% {Template OS Linux:vm.memory.size[available].last()} < 1G ``` --- **总结**:Linux内存风险不能仅凭单一百分比判断,需结合可用内存、Swap活动和具体应用场景综合分析。建议通过监控工具设置动态阈值,优先优化应用内存管理,其次调整系统参数,最后考虑硬件扩容。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值