先说结论解决办法:
一、在crontab定时执行echo 3> /proc/sys/vm/drop_caches清理缓存。治标不治本,过段时间缓存又会增加上来。
二、hcache -top 10查看下是哪些文件被缓存了,如果缓存的文件没有用就删除文件即可。删除文件后该文件的缓存将永久清除,但是系统难免会读取新文件什么的缓存可能还是有,可以结合第一个办法定期清理缓存。
三、把没用的日志文件清理删除掉,尤其是大日志文件,一般缓存就下去了。 find / -type f -size +1G -exec du -h {} \;
四、将vm.extra_free_kbytes设置为vm.min_free_kbytes和一样大,提高low阈值,触发操作系统自动回收缓存。https://www.cnblogs.com/panfeng412/p/drop-caches-under-linux-system-2.html
下面说我的处理过程:
服务器cache占了大半的内存导致内存不足,先释放cache保障服务正常运行再说:
手工释放缓存
先用root用户执行sync同步一下然后再执行echo 3> /proc/sys/vm/drop_caches
没多久,cache又涨回来了,这个cache是什么,能否限制大小?可以通过限制脏页比例来一定程度上调整。操作系统会在到了内存临界阈值后,触发kswapd内核进程工作进行释放。将vm.extra_free_kbytes设置为vm.min_free_kbytes和一样大,则/proc/zoneinfo中对应的low阈值就会增大一倍,同时high阈值也会随之增长
sudo sysctl -w vm.extra_free_kbytes=836787 ######1GB
参考Cache占用过多内存导致Linux系统内存不足问题排查 - AhaoMu - 博客园
cache是磁盘的读缓存,你程序操作过的文件从磁盘读到内存之后,linux操作系统会尽量保存这些文件在内存里,不到内存不足(vm.min_free_kbytes)不会主动释放。所以如果程序频繁读写文件会导致cache增加。内存不足的时候触发回收,但是这种清缓存的工作也并不是没有成本, 清缓存必须保证cache中的数据跟对应文件中的数据一致,才能对cache进行释放。所以伴随着cache清除的行为的,一般都是系统IO飙高。因为内核要对比cache中的数据和对应硬盘文件上的数据是否一致,如果不一致需要写回之后才能回收。
所以如何限制cache大小?可以通过设置最小空余内存以及触发回收的dirty_background_ratio和dirty_ratio来实现,生产上设置要小心,尤其空余内存不足的时候触发dirty_ratio强制进行缓存写磁盘时可能会阻塞应用造成机器hang死的情况。
限制缓存大小
触发异步清理
是内存可以填充“脏数据”的百分比。这些“脏数据”在稍后是会写入磁盘的,pdflush/flush/kdmflush这些后台进程会稍后清理脏数据。举一个例子,我有32G内存,那么有3.2G的内存可以待着内存里,超过3.2G的话就会有后来进程来清理它。
触发阻塞io,并将脏数据写进磁盘
是绝对的脏数据限制,内存里的脏数据百分比不能超过这个值。如果脏数据超过这个数量,新的IO请求将会被阻挡,直到脏数据被写进磁盘。这是造成IO卡顿的重要原因,但这也是保证内存中不会存在过量脏数据的保护机制。
hcache定位cache的工具https://github.com/silenceshell/hcache
wget https://silenceshell-1255345740.cos.ap-shanghai.myqcloud.com/hcache
chmod +x hcache
mv hcache /usr/local/bin
hcache -top 3
hcache -pid
取大小
hcache -pid 117466 | awk '{print $4}' > cache.txt
求和
I=0;$I=0; for N in $(cat cache.txt); do I=$(($I + $N)); done; echo $I
缓存查看利器hcache_04stone37-CSDN博客_hcache
这样统计了下,程序的cache并不多,都是缓存了jar包,但是为什么系统的cache那么高,看来这个hcache可能统计的并不全。看网上有说频繁写文件导致cache不断升高的文章,于是就想到了tomcat日志,一看总日志15G,7个G的catalina.out,清空catalina.out后,cache立马释放了7个G。很明显就是缓存的日志,日志大cache就多。
查找大于1G的文件
find / -type f -size +1G
使用cronlog将日志改为按日输出文件来减小日志文件大小,然后定期删除历史日志文件,解决。
另外,可以通过设置extra_free_kbytes系统最小内存剩余和会刷脏数据的参数来限制cache大小,如果没有extra_free_kbytes参数的,可以直接设置min_free_kbytes系统保留的最小内存(应用程序无法使用),单位为Kb,根据机器内存大小设置,100G的内存可以设置1G,多了浪费。
sysctl -w vm.min_free_kbytes=2097152
设置了min_free_kbytes之后,水位线会根据min_free_kbytes自动计算,
每个zone中的watermark[min/low/high]可以通过查看cat /proc/zoneinfo|grep -A10 ‘Node 0’的内容获得
到达low低水位时会触发kswap线程释放cache直到内存剩余达到high水位线才停止。如果内存剩余达到了min_free_kbytes则会触发直接内存回收,会造成系统卡顿甚至hang住。
在/proc/sys/vm
中有以下文件与回刷脏数据密切相关:
配置文件 | 功能 | 默认值 |
---|---|---|
dirty_background_ratio | 触发回刷的脏数据占可用内存的百分比 | 0 |
dirty_background_bytes | 触发回刷的脏数据量 | 10 |
dirty_bytes | 触发同步写的脏数据量 | 0 |
dirty_ratio | 触发同步写的脏数据占可用内存的百分比 | 20 |
dirty_expire_centisecs | 脏数据超时回刷时间(单位:1/100s) | 3000 |
dirty_writeback_centisecs | 回刷进程定时唤醒时间(单位:1/100s) | 500 |
总结下, cache是linux对读入内存的文件尽量不释放,这样可以减少重复的磁盘读,直到内存不足的时候才会释放,也不会释放完,有个水位线,达到水位线就停止继续释放。这都是linux的内存管理,无法从程序上进行控制,也不应该程序来控制。但是内存不足的时候回收cache会导致大量io,如果要避免这种情况则要定期清理日志并清理缓存sync&&echo 3 > /proc/sys/vm/drop_caches
另外,可以设置min_free_kbytes来提高水位线提前触发kswap进程回收缓存,以及根据业务情况设置dirty_ratio和dirty_background_ratio来触发脏数据回刷。
参考:https://lonesysadmin.net/2013/12/22/better-linux-disk-caching-performance-vm-dirty_ratio/
https://feichashao.com/dirty_ratio_and_dirty_background_ratio/
https://blog.csdn.net/cn_wk/article/details/80941151
https://www.kernel.org/doc/Documentation/sysctl/vm.txt?spm=a2c6h.13066369.0.0.87bd7b340Rvp7P&file=vm.txt
linux的cache过高的原因定位与解决_shy_snow的专栏-CSDN博客_cache过高
Cache占用过多内存导致Linux系统内存不足问题排查 - AhaoMu - 博客园
https://www.cnblogs.com/endv/p/9027432.html
linux内存管理中系统内存相关的参数说明(一)-Helianthus_lu-ChinaUnix博客