先说结论解决办法:

一、在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

  • To free pagecache释放页缓存:
    • echo 1 > /proc/sys/vm/drop_caches
  • To free reclaimable slab objects (includes dentries and inodes)释放slab对象:
    • echo 2 > /proc/sys/vm/drop_caches
  • To free slab objects and pagecache释放slab和页缓存:
    • echo 3 > /proc/sys/vm/drop_caches
  • To disable them, echo 4 (bit 2) into drop_caches.
  • 概念
    • inode是表示文件的数据结构
    • dentries是表示目录的数据结构
    • slab是Linux操作系统的一种内存分配机制,slab分配算法采用cache 存储内核对象。

没多久,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死的情况。

限制缓存大小

  • 查看配置
    • sysctl -a | grep dirty
  • 内存中有多少脏数据
    • cat /proc/vmstat | egrep "dirty|writeback"
  • vm.dirty_background_ratio
    • 触发异步清理

      是内存可以填充“脏数据”的百分比。这些“脏数据”在稍后是会写入磁盘的,pdflush/flush/kdmflush这些后台进程会稍后清理脏数据。举一个例子,我有32G内存,那么有3.2G的内存可以待着内存里,超过3.2G的话就会有后来进程来清理它。

  • vm.dirty_ratio
    • 触发阻塞io,并将脏数据写进磁盘

      是绝对的脏数据限制,内存里的脏数据百分比不能超过这个值。如果脏数据超过这个数量,新的IO请求将会被阻挡,直到脏数据被写进磁盘。这是造成IO卡顿的重要原因,但这也是保证内存中不会存在过量脏数据的保护机制。

  • vm.dirty_expire_centisecs
    • 脏数据存活的时间
  • vm.dirty_writeback_centisecs
    • 多长时间 pdflush/flush/kdmflush 这些进程会起来一次。
    • 100是1秒
  • 修改
    • /etc/sysctl.conf
    • 并执行
      • sysctl -p

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博客

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐