问题场景:
今天早上收到报警,系统剩余内存低于15%;这台机器运行的服务为nginx,理论上占用的内存不会很多,于是进行排查;
查看使用的内存:free -m
查看活跃进程使用的内存:ps aux --sort -rss | head
可以看到free -m使用的内存与前10个活跃进程使用的内存存在较在差距~
问题分析及解决:
通过查阅资料,有可能是slab占用了内存;
步骤一:安装atop工具,查看内存的具体使用情况
yum install atop -y
执行命令:atop
可以看到slab占用了2.6G的内存,确定了引用内存异常的原因是slab
步骤二:查看slab占用内存的具体情况
执行命令:cat /proc/meminfo | awk '{sum=$2/1024} {print $1 sum " MB"}' | grep claim
SReclaimable:3153.37 MB SUnreclaim:25.0664 MB
SReclaminable:表示可回收的slab占用的内存
SUnreclaim:表示不可回收的slab占用的内存
由此猜想,slab可回收的内存可以由系统进行自动回收或者手动回收
步骤三:查看具体是什么占用了slab内存
执行命令:slabtop
注:可以看到是dentry占用大部分的slab内存
slab内存分类:
pagecache
dentries:目录项高速缓存
inode
slab是Linux操作系统的一种内存分配机制。其工作是针对一些经常分配并释放的对象,您可以看看哪些应用进程的slab占用的内存比较多,是否这些应用需要频繁的请求和释放内存,比如进行一些小文件的读写。如果都是应用的正常使用,可以考虑升级服务器内存,如果内存不足影响业务,需要临时释放一下slab占用的内存;
slab内存的释放策略:
相关内核参数:vm.drop_caches
参数值含义:
0:不做任何处理,由系统自己管理
1:清空pagecache
2:清空dentries和inodes
3:清空pagecache、dentries和inodes
步骤四:手动回收slab中的可回收内存
#将内存的数据同步到磁盘
sync
#清空slab中可回收的内存
sudo sysctl -w vm.drop_caches=3 或者 echo 3 > /proc/sys/vm/drop_caches
#内存回收后把内核参数改为原来的值
sudo sysctl -w vm.drop_caches=0 或者 echo 0 > /proc/sys/vm/drop_caches
注:以上修改的方式是临时生效
相关内核参数:
vm.min_free_kbytes:保留给内核使用的;当到达min,系统会启动 kswapd 进行内存回收;此参数的默认值为67584;
可以通过此参数来的值让系统自动回收slab,但是此参数不宜设置过大;
由此此参数引发的血案:
生产中某台机器调高了此参数为1G,当系统free的内存小于1GB时,观察到kswapd进程开始工作(进程状态从Sleeping变为Running),同时dentry_cache开始被系统回收,直到系统free的内存介于low阈值和high阈值之间,停止回收。
如果系统的free内存一直低于1G,则kswapd一直运行,造成系统持续较大压力!