目录
问题描述
在后台接到监控的报警,提示Swap交换分区高占用,抓紧上去用 Top 及 free -h 看了下。 不看不知道,进入Top后按大写的M键,发现并没有想象中的高内存占用进程,于是立即用free -m 检查,终于发现了一些异常————系统的Buffer/Cache及Swap占用都很高。如何解决呢?
什么是Cache/Buffer?什么是Swap?
free -m 是大家经常用的Linux指令
# free -h
total used free shared buff/cache available
Mem: 32G 8.9G 8.2G 24M 24.4G 9.3G
Swap: 0B 0B 0B
什么是Cache/Buffer
Cache(Page cache,页面缓存):主要用来作为文件系统上的文件数据的缓存来用,尤其是针对当进程对文件有read/write操作的时候;历史上,buffer被用来当成对io设备写的缓存(不过现在已经几乎不这样干了)
Buffer(Buffer cache,缓冲区缓存):主要是针对块设备进行缓存的,比如当我们对一个文件进行写操作的时候,page cache的内容会被改变,而buffer cache则可以用来将page标记为不同的缓冲区,并记录是哪一个缓冲区被修改了。这样,内核在后续执行脏数据的回写(writeback)时,就不用将整个page写回,而只需要写回修改的部分即可。;历史上,cache被用来当作对io设备的读缓存不过现在已经几乎不这样干了)
Linux缓存(Cache)回收机制:Linux内核会在内存将要耗尽的时候,触发内存回收的工作,以便释放出内存给急需内存的进程使用。一般情况下,这个操作中主要的内存释放都来自于对buffer/cache的释放。尤其是被使用更多的cache空间。既然它主要用来做缓存,只是在内存够用的时候加快进程对文件的读写速度,那么在内存压力较大的情况下,当然有必要清空释放cache,作为free空间分给相关进程使用。所以一般情况下,我们认为buffer/cache空间可以被释放,这个理解是正确的。但是这种清缓存的工作也并不是没有成本。理解cache是干什么的就可以明白清缓存必须保证cache中的数据跟对应文件中的数据一致,才能对cache进行释放。所以伴随着cache清除的行为的,一般都是系统IO飙高。因为内核要对比cache中的数据和对应硬盘文件上的数据是否一致,如果不一致需要写回,之后才能回收。
什么是Swap
swap 分区通常被称为交换分区,这是一块特殊的硬盘空间,即当实际内存不够用的时候,操作系统会从内存中取出一部分暂时不用的数据,放在交换分区中,从而为当前运行的程序腾出足够的内存空间。也就是说,当内存不够用时,我们使用 swap 分区来临时顶替。这种“拆东墙,补西墙”的方式应用于几乎所有的操作系统中。
使用 swap 交换分区,显著的优点是,通过操作系统的调度,应用程序实际可以使用的内存空间将远远超过系统的物理内存。由于硬盘空间的价格远比 RAM 要低,因此这种方式无疑是经济实惠的。当然,频繁地读写硬盘,会显著降低操作系统的运行速率,这也是使用 swap 交换分区最大的限制。
Cache/Buffer 及 Swap 过大会导致哪些问题?
在Linux的内存管理机制中,Linux内核会在内存将要耗尽的时候,触发内存回收的工作,以便释放出内存给急需内存的进程使用。一般情况下,这个操作中主要的内存释放都来自于对buffer/cache的释放。尤其是被使用更多的cache空间。既然它主要用来做缓存,只是在内存够用的时候加快进程对文件的读写速度,那么在内存压力较大的情况下,当然有必要清空释放cache,作为free空间分给相关进程使用。所以一般情况下,我们认为buffer/cache空间可以被释放,这个理解是正确的。
但是这种清缓存的工作也并不是没有成本。理解cache是干什么的就可以明白清缓存必须保证cache中的数据跟对应文件中的数据一致,才能对cache进行释放。所以伴随着cache清除的行为的,一般都是系统IO飙高。因为内核要对比cache中的数据和对应硬盘文件上的数据是否一致,如果不一致需要写回,之后才能回收。
swap分区不是必须的,主要作用是,当物理内存不够的时候,将内存中的部分不活跃数据临时存到硬盘。这个想法很好,但是现实往往很残酷,当物理内存不够的时候,你把几个G的内存写到硬盘,然后又读出来,那磁盘io是相当大的,io过高会让服务器的负载过高,影响服务器整体性能,严重可能导致服务器卡死。现在很多服务,比如k8s都是直接让你禁用swap。所以主要要靠管理员以及开发好好管理服务器内存,swap什么的有时候并没有什么用。
总结起来就是,当Cache/Buffer及Swap内存过高时,会带来磁盘IO过高的隐患。前者是因为对将文件从内存写入到磁盘的过程中,会进行文件内容校验,引发大量的IO。后者则由于当Swap过大时,怕频繁的磁盘读写,导致较大的IO。
解决方法
手动清除Cache/Buffer
#将所有未写的系统缓冲区写到磁盘中,包含已修改的 i-Node、已延迟的块 I/O 和读写映射文件,确保文件系统的完整性
sync
#执行清理内存指令
#0:不释放(系统默认值)
#1:释放页缓存
#2:释放dentries和inodes
#3:释放所有缓存
echo 1 > /proc/sys/vm/drop_caches
echo 2 > /proc/sys/vm/drop_caches
echo 3 > /proc/sys/vm/drop_caches
释放后free -m查看内存占用情况cache明显减少
#恢复内存清理策略为不清理
echo 0 > /proc/sys/vm/drop_caches
调整swap
== 在检查内存足够Swap切换时,再进行切换,否则会宕机 ==
== 这里直接使用了Swapon 和 Swapoff , 关掉Swap,交换分区所有数据转移到内存,再打开Swap ==
swapoff -a && swapoff -a