现象
我们在使用free -h查看系统内存的时候,有时间会发现buff/cache很高
原理
cache与buffer解读
cache出现的原因与功能 计算机硬件中CPU、内存、磁盘是最主要的三大部分,其中,CPU发展到今天,执行速度最快,而内存相对CPU而言,就慢多了,CPU执行的指令是从内存取出的,计算的结果也要写回内存,但内存的响应速度如果跟不上CPU的话,CPU只能无所事事的等待了。这样一来,再快的CPU也发挥不了效率。
同理,内存中的数据也要回写到磁盘的,相对于机械硬盘HDD,内存的速度可快多了。这就又出现了问题,磁盘的低速读写速度,相比内存条的二进制电压变化速度,那就是蒸汽机和火箭速度的差别。这样巨大差异,即使内存读写速度再快,还是要被磁盘的低速读写拖后腿。
所谓Cache,就是“为了弥补高速设备和低速设备之间的矛盾”而设立的一个中间层。因为在现实里经常出现高速设备要和低速设备打交道,结果被低速设备拖后腿的情况。
buffer出现的原因以及与cached的比较
buffer,它存在的目的适用于速度快的设备往速度慢的设备输出东西。例如内存的数据要写到磁盘,cpu寄存器里的数据写到内存。缓冲(buffers)是根据磁盘的读写设计的,它把分散的写操作集中进行,减少磁盘碎片和硬盘的反复寻道,从而提高系统性能。
总结:
1)、cached是cpu与内存间的,buffer是内存与磁盘间的,都是为了解决速度不对等的问题
2)缓存(cached)是把读取过的数据保存起来,重新读取时若命中(找到需要的数据)就不要去读硬盘了,若没有命中就读硬盘。
3)buffer是即将要被写入磁盘的,而cache是被从磁盘中读出来的
4)在应用场景上,buffer是由各种进程分配的,被用在如输入队列等方面。
Linux内存管理中page cache与buffer cache机制
下面我们结合cpu、内存、磁盘IO来看一下这种读、写缓存模型,如右图所示:
从图中可以看出,有读、写两条线。磁盘数据会被读取到Page cache进行缓存,程序要读取数据的时候,可以直接从Page cache读取,这是读取数据的一条线路。
此外,当page cache的数据需要刷新时,page cache中的数据会交给buffer cache,而Buffer cache中的所有数据都会定时刷新到磁盘。这些写入数据的另一条线。
page cache是文件系统层面的缓存,它从磁盘里面读取的内容都会存储在这里,这样应用程序在读取磁盘的内容就会非常的快,因为直接从pagecahce里面读取就行了,比如通过find命令查找某些文件,某些内容的时候,第一次查找的速度比较慢,第二次执行的时候瞬间就完成了,原因就是查找的文件都被缓存到pagecahce里面去了,再次查找就从内存里面读取这些文件,这样速度就会快很多。
buffer其实是磁盘和块设备的一个缓冲,这部分内存数据是最终要写入到磁盘的,不是及时写入磁盘的,它是等系统空闲或者buffer达到了一定大小的时候,统一写到磁盘当中的,所以系统断电的时候这部分数据可能会丢失。所以为了防止数据的丢失,在关机的时候多执行几次sync的命令,这样做的就是立刻将buffer中数据写入磁盘,操作系统也有定时同步的机制,它也会定时的去执行sync命令将内存 buffer/cahce数据刷到磁盘。
解决方案
手动清除buff/cache
> sync
> echo 1 > /proc/sys/vm/drop_caches
> echo 2 > /proc/sys/vm/drop_caches
> echo 3 > /proc/sys/vm/drop_caches
- sync:将所有未写的系统缓冲区写到磁盘中,包含已修改的i-node、已延迟的块I/O和读写映射文件
- echo 1 > /proc/sys/vm/drop_caches:清除page cache
- echo 2 > /proc/sys/vm/drop_caches:清除回收slab分配器中的对象(包括目录项缓存和inode缓存)。slab分配器是内核中管理内存的一种机制,其中很多缓存数据实现都是用的pagecache。
- echo 3 > /proc/sys/vm/drop_caches:清除pagecache和slab分配器中的缓存对象。
/proc/sys/vm/drop_caches的值,默认为0
定时任务清除
> vim clean.sh
#!/bin/bash#每两小时清除一次缓存
echo "开始清除缓存"
sync;sync;sync #写入硬盘,防止数据丢失
sleep 20#延迟20秒
echo 1 > /proc/sys/vm/drop_caches
echo 2 > /proc/sys/vm/drop_caches
echo 3 > /proc/sys/vm/drop_caches
> chmod +x clean.sh
> crontab -e
# 每两小时执行一次
0 */2 * * * /opt/clean.sh
设置crond启动以及开机自启
systemctl start crond.service
systemctl enable crond.service