Linux系统free命令的buff/cache占用过高
背景
Java程序运行时间长了,使用free -h
命令时经常会发现buff/cache占用相当高,甚至会因为占用太高内存而导致Java应用程序崩溃。
解决方案
free命令简介
先来说一下free命令
[root@centos demo]# free -h
total used free shared buff/cache available
Mem: 31G 22G 9.1G 8.8M 202M 8.9G
Swap: 14G 1.8M 14G
其中:
total 内存总数
used 已经使用的内存数
free 空闲的内存数
shared 多个进程共享的内存总额
buffers Buffer Cache和cached Page Cache 磁盘缓存的大小
-buffers/cache 的内存数:used - buffers - cached
+buffers/cache 的内存数:free + buffers + cached
然后我们来搞点有意思的:如果我执行复制文件,内存会发生什么变化。
[root@centos demo]# cp -r /var /data/demo/
[root@centos demo]# free -h
total used free shared buff/cache available
Mem: 31G 22G 1.0G 8.8M 8.1G 8.7G
Swap: 14G 1.8M 14G
在我命令执行结束后,used为22G,free为1.0G,buff/cache为8.1G,和我们刚才执行free命令的时候对比,发现竟有近8个G的内存都被buff/cache吃掉了。别紧张,这是为了提高文件读取效率的做法。
为了提高磁盘存取效率,Linux做了一些精心的设计,除了对dentry进行缓存(用于VFS,加速文件路径名到inode的转换),还采取了两种主要Cache方式:BufferCache和PageCache。前者针对磁盘块的读写,后者针对文件inode的读写。这些Cache有效缩短了I/O系统调用(比如read,write,getdents)的时间。
接着来,就让我们手动释放掉这些内存吧。
sync命令简介
sync命令用于强制被改变的内容立刻写入磁盘,更新超块信息。
在Linux/Unix系统中,在文件或数据处理过程中一般先放到内存缓冲区中,等到适当的时候再写入磁盘,以提高系统的运行效率。sync命令则可用来强制将内存缓冲区中的数据立即写入磁盘中。用户通常不需执行sync命令,系统会自动执行update或bdflush操作,将缓冲区的数据写 入磁盘。只有在update或bdflush无法执行或用户需要非正常关机时,才需手动执行sync命令。
buffer与cache
- buffer:为了解决写磁盘的效率
- cache:为了解决读磁盘的效率
linux系统为了提高读写磁盘的效率,会先将数据放在一块buffer中。在写磁盘时并不是立即将数据写到磁盘中,而是先写入这块buffer中了。此时如果重启系统,就可能造成数据丢失。
sync命令用来flush文件系统buffer,这样数据才会真正的写到磁盘中,并且buffer才能够释放出来,flush就是用来清空buffer。sync命令会强制将数据写入磁盘中,并释放该数据对应的buffer,所以常常会在写磁盘后输入sync命令来将数据真正的写入磁盘。
如果不去手动的输入sync命令来真正的去写磁盘,linux系统也会周期性的去sync数据。
手动释放缓存
/proc是一个虚拟文件系统,我们可以通过对它的读写操作做为与kernel实体间进行通信的一种手段。也就是说可以通过修改/proc中的文件,来对当前kernel的行为做出调整。那么我们可以通过调整/proc/sys/vm/drop_caches来释放内存。操作如下:
查看/proc/sys/vm/drop_caches的值,默认为0。
[root@centos demo]# cat /proc/sys/vm/drop_caches 0
执行sync命令
描述:sync 命令运行 sync子例程。如果必须停止系统,则运行sync 命令以确保文件系统的完整性。sync命令将所有未写的系统缓冲区写到磁盘中,包含已修改的 i-node、已延迟的块 I/O和读写映射文件。
[root@centos demo]# sync
将/proc/sys/vm/drop_caches值设为3
[root@centos demo]# echo 3 > /proc/sys/vm/drop_caches [root@centos demo]# cat /proc/sys/vm/drop_caches
再运行free命令,会发现现在的used为22G,free为9.2G,buff/cache为93M。那么有效的释放了buff/cache。
[root@centos demo]# free -h total used free shared buff/cache available Mem: 31G 22G 9.2G 8.8M 93M 9.0G Swap: 14G 1.8M 14G
总结
执行以下命令:
sync && echo 1 > /proc/sys/vm/drop_caches
sync && echo 2 > /proc/sys/vm/drop_caches
sync && echo 3 > /proc/sys/vm/drop_caches
drop_caches的值可以是0-3之间的数字,代表不同的含义:
0:不释放(系统默认值)
1:释放页缓存
2:释放dentries和inodes
3:释放所有缓存
其他:
- 可以设置定时任务执行:
这里可以考虑用定时器,几天或者几小时执行一次。
执行:crontab -e
然后在配置文件中加入 0 4 * * * sync && echo 1 > /proc/sys/vm/drop_caches
表示每天凌晨4点清理1次buff/cache,当然这个执行周期可以随意设置。 - 注意:在执行这三条命令之前一定要先执行sync命令(描述:sync 命令运行 sync 子例程。如果必须停止系统,则运行sync 命令以确保文件系统的完整性。
sync 命令将所有未写的系统缓冲区写到磁盘中,包含已修改的 i-Node、已延迟的块 I/O 和读写映射文件)
不过,一般情况下,应用在系统上稳定运行了,free值也会保持在一个稳定值的,虽然看上去可能比较小。
当发生内存不足、应用获取不到可用内存、OOM错误等问题时,还是更应该去分析应用方面的原因,如用户量太大导致内存不足、发生应用内存溢出等情况,否则,清空buffer,强制腾出free的大小,可能只是把问题给暂时屏蔽了。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!