还原下现场:
某天下午, 运营反馈说网页打开很卡。经过排查发现服务器内存被写满,除了内存被写满以后, 其他都是正常的。
- 内存大部分都是被used
- cache并没有占用多少
处理方案:
首先紧急释放内存
使用命令
echo 3 > /proc/sys/vm/drop_caches
在我的理解上, 内存是会自动回收的。但是这次很明显是并没有回收内存引起的。
所以花了点时间研究了一下内存的回收机制:
Linux 内存回收机制这篇文章给了我很多引发, 特别感谢大神, 让我理解了以前很多不理解的东西。
首先来说下手动释放内存命令:
echo 1 > /proc/sys/vm/drop_caches #free pagecache, use
echo 2 > /proc/sys/vm/drop_caches #free dentries and inodes
echo 3 > /proc/sys/vm/drop_caches #free pagecache, dentries and inodes
pagecahe: 很好理解,就是缓存
dentries: dentries是表示目录的数据结构
inodes: inode是表示文件的数据结构好吧, 对于以上 dentries 和 inodes的解释我是在不知道他们是干啥的。。先挖坑,以后再填吧。
但至少我发现了这张图
根据事故原因, 我需要做的就是释放 dentries和inodes,但为什么没有被释放?
** 按图上描述linux有3种释放dentries和inodes的方式: **
- 快速释放内存,又分4种情况, 根据参数 /proc/sys/vm/zone_reclaim_mode:
-. 0x0: 当此参数为0时,会导致快速内存回收只会对最优zone附近的几个需要进行内存回收的zone进行内存回收(说快速内存会解释),而只要不为0,就会对zonelist中所有应该进行内存回收的zone进行内存回收。
-. 0x1:开启zone的内存回收
-. 0x2:开启zone的内存回收,并且允许回写
-. 0x4:开启zone的内存回收,允许进行unmap操作- 直接释放,也分两种情况, 根据参数 /proc/sys/vm/laptop_mode:
-. 0:允许直接内存回收对匿名页lru链表中的页进行回写操作,并且允许直接内存回收唤醒flush内核线程
-. 非0:直接内存回收不会对匿名页lru链表中的页进行回写操作- kwapd回收, 根据 /proc/sys/vm/swappiness参数来合理分配 扫描匿名页lru链表和扫描文件页lru链表的比例:
-. 接近0:进行内存回收时,更多地去扫描文件页lru链表,如果为0,那么就不会去扫描匿名页lru链表。
-. 接近200:进行内存回收时,更多地去扫描匿名页lru链表。
** 还有3种回收限制:**
-. ALLOC_WMARK_MIN: 内存不足的最低点,如果计算出的可用页面低于该值,则无法进行页面计数(可根据/proc/sys/vm/min_free_kbytes设置);
-. ALLOC_WMARK_LOW: 默认情况下,该值为WMARK_MIN的125%,此时kswapd将被唤醒,可以通过修改/proc/sys/vm/watermark_scale_facto来改变比例值;
-. ALLOC_WMARK_HIGH: 默认情况下,该值为WMARK_MAX的150%,此时kswapd将睡眠,可以通过修改/proc/sys/vm/watermark_scale_facto来改变比例值;
有了上面的几个参数配置,挨个检查:
[root@web03 mysql]# cat /proc/sys/vm/zone_reclaim_mode
0
[root@web03 mysql]# cat /proc/sys/vm/laptop_mode
0
[root@web03 mysql]# cat /proc/sys/vm/swappiness
60
所以很容易看出来问题是并没有开启zone的内存回收
虽然问题找到了,但是还得学习linux相关知识。
最后感谢 下面两位大神写的文章
Linux 内存回收机制
Linux内存管理,Linux内存管理