前言
近期一台服务器内存的free很少,但是buff/cache很高。实际服务器上也业务也受到了一定影响。但自己对buff/cache这一块的认识很模糊,所以记录一下从其他博客学习到的东西。
服务器内存使用是这样的。
admin@ip-10-100-13-245:~$ free -hm
total used free shared buff/cache available
Mem: 30G 14G 423M 10M 15G 15G
Swap: 0B 0B 0B
补充:如何分别查看buff/cache占用了多少内存
使用-w,--wide参数
root@ip-10-100-13-245:/home/admin# free -hmw
total used free shared buffers cache available
Mem: 30G 14G 865M 10M 106M 15G 15G
Swap: 0B 0B 0B
buff和cache的区别
参考文档:Linux内存Cache和Buffer理解_CoderLife9192的专栏-CSDN博客
学习中,博文中提到。我们对于内存的认识主要有下面三个阶段:
- 不了解。这样的人的第一反应是:天啊,内存用了好多,70个多 G,可是我几乎没有运行什么大程序啊?为什么会这样? Linux 好占内存!
- 自以为很了解。这样的人一般评估过会说:嗯,根据我专业的眼光看的出来,内存才用了 17G 左右,还有很多剩余内存可用。buffers/cache 占用的较多,说明系统中有进程曾经读写过文件,但是不要紧,这部分内存是当空闲来用的。
- 真的很了解。这种人的反应反而让人感觉最不懂 Linux,他们的反应是:free 显示的是这样,好吧我知道了。神马?你问我这些内存够不够,我当然不知道啦!我特么怎么知道你程序怎么写的?
我对号入座了一下,我就处于第二阶段(自以为很了解)。大家普遍认为,buffers 和 cached 所占用的内存空间是可以在内存压力较大的时候被释放当做空闲空间用的。但真的是这样么?在论证这个题目之前,我们先简要介绍一下 buffers 和 cached 是什么意思:
什么是 buffer/cache?
buffer 和 cache 是两个在计算机技术中被用滥的名词,放在不同语境下会有不同的意义。在 Linux 的内存管理中。
(其实到这里,你可以最初步的认识buff/cache的区别)
buffer 指 Linux 内存的:Buffer cache,(buffer)被用来当成对 io 设备写的缓存;
cache 指 Linux 内存中的:Page cache,(cache)被用来当作对 io 设备的读缓存。
翻译成中文可以叫做缓冲区缓存和页面缓存。这里的 io 设备,主要指的是块设备文件和文件系统上的普通文件。但是现在,它们的意义已经不一样了。
在当前的内核中,page cache 顾名思义就是针对内存页的缓存,说白了就是,如果有内存是以 page 进行分配管理的,都可以使用 page cache 作为其缓存来管理使用。当然,不是所有的内存都是以页page进行管理的,也有很多是针对块block进行管理的,这部分内存使用如果要用到 cache 功能,则都集中到 buffer cache 中来使用。(从这个角度出发,是不是 buffer cache 改名叫做 block cache 更好?)然而,也不是所有块block都有固定长度,系统上块的长度主要是根据所使用的块设备决定的,而页长度在 X86 上无论是32位还是64位都是 4k。
明白了这两套缓存系统的区别,就可以理解它们究竟都可以用来做什么了。
什么是 page cache?
Page cache 主要用来作为文件系统上的文件数据的缓存来用,尤其是针对当进程对文件有 read/write 操作的时候。如果你仔细想想的话,作为可以映射文件到内存的系统调用:mmap 是不是很自然的也应该用到 page cache?在当前的系统实现里, page cache 也被作为其它文件类型的缓存设备来用,所以事实上 page cache 也负责了大部分的块设备文件的缓存工作。
什么是 buffer cache?
Buffer cache 则主要是设计用来在系统对块设备进行读写的时候,对块进行数据缓存的系统来使用。这意味着某些对块的操作会使用 buffer cache 进行缓存,比如我们在格式化文件系统的时候。一般情况下两个缓存系统是一起配合使用的,比如当我们对一个文件进行写操作的时候,page cache 的内容会被改变,而 buffer cache 则可以用来将 page 标记为不同的缓冲区,并记录是哪一个缓冲区被修改了。这样,内核在后续执行脏数据的回写writeback时,就不用将整个 page 写回,而只需要写回修改的部分即可。
cache回收原理
可回收的cache
Linux 内核会在内存将要耗尽的时候,触发内存回收的工作,以便释放出内存给急需内存的进程使用。一般情况下,这个操作中主要的内存释放都来自于对 buffer/cache 的释放。尤其是被使用更多的 cache 空间。既然它主要用来做缓存,只是在内存够用的时候加快进程对文件的读写速度,那么在内存压力较大的情况下,当然有必要清空释放 cache,作为 free 空间分给相关进程使用。所以一般情况下,我们认为 buffer/cache 空间可以被释放,这个理解是正确的。
但是这种清缓存的工作也并不是没有成本。理解 cache 是干什么的就可以明白清缓存必须保证 cache 中的数据跟对应文件中的数据一致,才能对 cache 进行释放。所以伴随着 cache 清除的行为的,一般都是系统 IO 飙高。因为内核要对比 cache 中的数据和对应硬盘文件上的数据是否一致,如果不一致需要写回,之后才能回收。
不可回收的cache
(原博客中博主对不可回收的内存有详细的测试演示,强烈推荐大家参考)
Linux 系统内存中的 cache 并不是在所有情况下都能被释放当做空闲空间用的。并且也也明确了,即使可以释放 cache,也并不是对系统来说没有成本的。总结一下要点,我们应该记得这样几点:
- 当 cache 作为文件缓存被释放的时候会引发 IO 变高,这是 cache 加快文件访问速度所要付出的成本。
- tmpfs 中存储的文件会占用 cache 空间,除非文件删除否则这个 cache 不会被自动释放。
- 使用 shmget 方式申请的共享内存会占用 cache 空间,除非共享内存被 ipcrm 或者使用 shmctl 去 IPC_RMID,否则相关的 cache 空间都不会被自动释放。
- 使用 mmap 方法申请的 MAP_SHARED 标志的内存会占用 cache 空间,除非进程将这段内存 munmap,否则相关的 cache 空间都不会被自动释放。
- 实际上 shmget、mmap 的共享内存,在内核层都是通过 tmpfs 实现的,tmpfs 实现的存储用的都是 cache。
cache回收操作
参考文档:Linux下内存buff cache占用过多问题解决 - 简书
看到buff/cache占用的内存非常大,这个时候可以使用一下命令去清除一下cache内存
前面加sync 是为了防止内容丢失
sync;echo 1 > /proc/sys/vm/drop_caches
sync;echo 2 > /proc/sys/vm/drop_caches
sync;echo 3 > /proc/sys/vm/drop_caches
这个文件可以设置的值分别为1、2、3。它们所表示的含义为:
echo 1 > /proc/sys/vm/drop_caches # 表示清除pagecache。
echo 2 > /proc/sys/vm/drop_caches # 表示清除回收slab分配器中的对象(包括目录项缓存和inode缓存)。slab分配器是内核中管理内存的一种机制,其中很多缓存数据实现都是用的pagecache。
echo 3 > /proc/sys/vm/drop_caches # 表示清除pagecache和slab分配器中的缓存对象。
sync命令补充
sync命令_Linux sync 命令用法详解:用于强制被改变的内容立刻写入磁盘
sync命令用于将linux中的buffer缓存数据写入到磁盘中。linux系统为了提高写入操作效率,会先将数据写入到内存缓冲区,等适当时候再写入磁盘。
参考文档
Linux内存Cache和Buffer理解_CoderLife9192的专栏-CSDN博客https://linux.cn/article-7310-1.html 在 Linux 系统中,我们经常用 free 命令来查看系统内存的使用状态。在一个 RHEL6 的系统上,free 命令的显示内容大概是这样一个状态: [root@tencent64 ~]# freetotal used free shared buffers cachedMem: 1322569...https://blog.csdn.net/lqglqglqg/article/details/82313966Linux下内存buff cache占用过多问题解决 - 简书在Linux下经常会遇到buff/cache内存占用过多问题,尤其是使用云主机的时候最严重,由于很多是虚拟内存,因此如果buff/cache占用过大的,free空闲内存就很少...https://www.jianshu.com/p/6cddda367ed0?utm_campaign=maleskine...&utm_content=note&utm_medium=seo_notes&utm_source=recommendation