linux buff/cache过大,清理脚本

本文分享了解决Linux系统中因内存使用量超过阈值导致Java应用崩溃的方案。通过分析发现,问题根源在于文件缓存(Cached)值过高,消耗大量内存。作者通过执行特定指令释放缓存并编写shell脚本配合定时任务,实现内存的自动清理,有效避免了程序崩溃。

问题描述

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脚本。
--------------------- 
原文:https://blog.youkuaiyun.com/u014740338/article/details/66975550 
版权声明:本文为博主原创文章,转载请附上博文链接!

<think> 我们之前已经讨论过,Linux系统的buff/cache是由内核自动管理的,用户无法直接设置一个固定的缓存小。但是,我们可以通过一些方法来间接地增加系统用于buff/cache的内存量。根据之前的讨论和引用,以下是几种有效的方法: ### 1. **增加物理内存(RAM)** - **原理**:buff/cache使用的是空闲内存,因此增加物理内存是最直接的方法。当系统有更多的RAM时,内核会自动将多余的内存用于磁盘缓存,从而增加buff/cache。 - **操作**: 1. 关闭服务器,安装新的内存条(物理服务器)或在云控制台升级实例配置(云服务器)。 2. 重启服务器,系统会自动利用新增的内存作为缓存。 - **验证**:重启后使用`free -h`命令查看,观察`buff/cache`列是否增加。 ### 2. **优化应用程序内存使用** - **原理**:如果应用程序占用了量内存,内核会减少缓存分配。通过降低应用内存占用,可以使更多内存空闲,从而被内核用作buff/cache。 - **操作**: 1. 使用`top`或`htop`找出内存消耗的进程(按`Shift+M`排序)。 2. 调整应用配置以减少内存占用(如减少Java堆小、调整数据库缓存小等)。 3. 重启相关服务后,观察`free`命令中`buff/cache`是否增长。 ### 3. **调整内核参数(谨慎使用)** - **原理**:通过修改内存管理参数,可以影响内核回收缓存的策略,从而让系统保留更多缓存。但过度调整可能导致内存不足(OOM)。 - **操作**(参考引用[2][3]): - **降低缓存回收压力**: ```bash # 临时生效(重启后失效) sudo sysctl vm.vfs_cache_pressure=50 ``` 或永久生效: ```bash echo "vm.vfs_cache_pressure=50" | sudo tee -a /etc/sysctl.conf sudo sysctl -p ``` - 参数说明:默认值为`100`,降低该值(如`50`)会使内核更倾向于保留目录项(dentries)和inode缓存[^2][^3]。 - **调整脏页写回策略**(增加缓存停留时间): ```bash # 增加脏页在内存中停留的阈值(单位:百分比,默认10%) sudo sysctl vm.dirty_background_ratio=20 sudo sysctl vm.dirty_ratio=40 ``` 永久生效: ```bash echo "vm.dirty_background_ratio=20" | sudo tee -a /etc/sysctl.conf echo "vm.dirty_ratio=40" | sudo tee -a /etc/sysctl.conf sudo sysctl -p ``` - 参数说明: - `vm.dirty_background_ratio`:当脏页占总内存比例超过此值时,内核在后台开始写回(异步)。 - `vm.dirty_ratio`:当脏页比例超过此值时,新写入操作会被阻塞(同步写回)[^2]。 - **风险提示**:设置过高可能导致数据丢失风险(停电时未写入磁盘的数据增多)。 ### 4. **避免手动清理缓存** - **重要提示**:引用[1][2][3][4]中提到的`echo 3 > /proc/sys/vm/drop_caches`命令会强制释放缓存,**这与增加缓存的目标相反**。因此,切勿定期执行此类操作(如引用[4]的定时任务),否则会人为减少缓存量[^1][^2][^3][^4]。 ### 监控与验证 - **查看缓存变化**: ```bash watch -n 1 "free -h; echo; grep -E '^Cached|^Buffers|^Dirty' /proc/meminfo" ``` - **性能测试**:使用`dd`或`fio`工具测试文件读取速度,观察缓存命中后的速度提升。 ### 总结 - **核心原则**:Linux缓存机制是自动的,增加缓存的本质是**提供更多空闲内存**(物理扩容)或**减少内存竞争**(应用优化/参数调整)。 - **推荐优先级**:物理扩容 > 应用优化 > 内核参数调整(后者需充分测试)。 §§相关问题§§ 1. 调整`vm.vfs_cache_pressure`和`vm.dirty_ratio`参数时,如何避免系统出现OOM(内存不足)问题? 2. 除了`free`命令,还有哪些工具可以详细分析Linux系统的缓存使用情况? 3. 在云服务器(如AWS、阿里云)上升级内存的具体操作步骤是什么? </think> ### 如何增加Linux服务器buff/cache缓存容量 在Linux系统中,buff/cache是内核自动管理的磁盘缓存机制,无法直接设置固定小,但可通过以下方法间接增加其容量: --- #### 1. **增加物理内存(核心方法)** [推荐] - **原理**:buff/cache使用空闲内存,物理RAM增加后内核会自动分配更多内存作为缓存 - **操作**: 1. 添加内存硬件(物理服务器)或升级云实例配置(云服务器) 2. 重启后验证: ```bash free -h # 观察buff/cache列增长 ``` ```text # 示例输出(升级后) total used free shared buff/cache available Mem: 32G 8G 2G 1G 22G 23G ``` - **优势**:最安全有效的方式,无性能损耗 --- #### 2. **优化内存分配策略** - **调整内核参数**(谨慎操作): ```bash # 降低缓存回收压力(默认值100,减小保留更多缓存) sudo sysctl vm.vfs_cache_pressure=50 # 增加脏页缓存时间(默认10%,调高延长缓存保留) sudo sysctl vm.dirty_background_ratio=15 sudo sysctl vm.dirty_ratio=30 ``` 永久生效配置: ```bash echo "vm.vfs_cache_pressure=50" >> /etc/sysctl.conf echo "vm.dirty_background_ratio=15" >> /etc/sysctl.conf echo "vm.dirty_ratio=30" >> /etc/sysctl.conf sysctl -p ``` - **风险提示**: - 过度调低可能导致内存不足(OOM) - 建议梯度调整(每次10%),监控`/proc/meminfo` --- #### 3. **减少内存竞争** - **优化应用内存使用**: 1. 通过`top`或`htop`识别高内存进程(按`Shift+M`) 2. 调整关键服务配置: - MySQL:降低`innodb_buffer_pool_size` - Java:调整`-Xmx`堆内存上限 3. 释放的内存会自动转为buff/cache - **停止缓存清理操作**: - **禁止定时清理脚本**(引用[4]中的方法会减少缓存) - 避免手动执行`echo 3 > /proc/sys/vm/drop_caches`[^1][^2][^3] --- #### 4. **监控与验证** - 实时观察缓存增长: ```bash watch -n 1 "grep -E 'Buffers|Cached|Dirty' /proc/meminfo" ``` 输出示例: ```text Buffers: 1024 kB Cached: 20480 kB Dirty: 512 kB ``` - 性能测试工具: ```bash # 测试缓存加速效果(首次读取慢,二次读取加速) hdparm -Tt /dev/sda1 ``` --- ### 关键注意事项 1. **勿强制清理缓存**:引用[1][2][3]中的`drop_caches`操作会减少缓存,与目标相反[^1][^2][^3] 2. **监控优先**:调整前后使用`vmstat 2`观察`cache`列变化 3. **云服务器限制**:云环境(如ECS)的虚拟内存机制可能限制缓存增长(引用[2])[^2] 4. **梯度调整**:内核参数每次调整不超过20%,观察24小时再迭代 > **缓存本质**:Linuxbuff/cache是空闲内存的**自然利用**,最优策略是保持充足物理内存并避免人为干预回收。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值