广州小码王教育

记一次内存占用问题的调查过程

作者:网友提供 来源:小码王少儿编程 时间:2020-02-21

  最近在维护一台CentOS服务器的时候,发现内存无端"损失"了许多,free和ps统计的结果相差十几个G,搞的我一度又以为遇到灵异事件了,后来Google了许久才搞明白,特此记录一下,以供日后查询。
  虽然天天都在用Linux系统办公,其实对它的了解也不过尔尔。毕业几年才迈入"知道自己不知道"的境界,我觉得自己丝毫没有愧对万年吊车尾这个称号 :(
  同事说有一台服务器的内存用光了,我连上去用free看了下,确实有点怪。

$ free -g
             total       used       free     shared    buffers     cached
Mem:            15         15          0          0          2          0
-/+ buffers/cache:         12          2
Swap:           17          0         17

  这台服务器有16G内存,但是结果显示除了2G左右的文件Buffer缓存外,其余十几G都被确确实实的用光了。(free按1024进制计算,总内存可能比实际偏小)
  这里大概介绍下free结果的含义:

/totalusedfreesharedbufferscached
Mem总物理内存当前使用的内存(包括slab+buffers+cached)完全没有使用的内存进程间共享的内存缓存文件的元数据1缓存文件的具体内容1
-/+ buffers/cache当前使用的内存(不包括buffers+cached,但包括slab)未使用和缓存的内存(free+buffers+cached)
Swap总的交换空间已使用的交换空间未使用的交换空间

  然后top看了下,没有特别吃内存的程序。用ps大概统计下所有程序占用的总内存:

$ ps aux | awk '{mem += $6} END {print mem/1024/1024}'
0.595089

  结果显示所有进程占用的内存还不到1G,实际上,因为free, ps的统计方式的差别和Copy-on-write和Shared libraries等内存优化机制的存在,这两者的统计结果通常是不一样的。但是一般情况下**不会相差十几个G,肯定是有什么隐藏的问题,Google了许久后发现,free没有专门统计另一项缓存: Slab。
  Slab Allocation是Linux 2.2之后引入的一个内存管理机制,专门用于缓存内核的数据对象,可以理解为一个内核专用的对象池,可以提高系统性能并减少内存碎片。(Linux 2.6.23之后,SLUB成为了默认的allocator。)
  查看Slab缓存

$ cat /proc/meminfo

其中,Slab相关的数据为

Slab:             154212 kB
SReclaimable:      87980 kB
SUnreclaim:        66232 kB

SReclaimable(Linux 2.6.19+)都是clean的缓存,随时可以释放。回到之前的内存问题,我查了下那台服务器上Slab占用的内存:

$ cat /proc/meminfo | grep Slab
Slab:         12777668 kB

  12G的Slab缓存,有意思的是free把Slab缓存统计到了used memory中,这就是之前那个问题的症结所在了。
  另外,还可以查看/proc/slabinfo(或使用slabtop命令)来查看Slab缓存的具体使用情况。结果发现,ext3_inode_cache和dentry_cache占用了绝大部分内存。
  考虑到这台服务器会频繁地用rsync同步大量的文件,这个结果也并不意外。
  先说明一下,如果问题仅仅是Slab占用了太多的内存(SReclaimable),那么通常不需要太操心,因为这根本不是个问题(如果是 SUnreclaim太多且不断增长,那么很有可能是内核有bug)。但是,如果是因为Slab占用内存太多而引起了其他的问题,建议继续阅读。
  清除Slab可回收缓存
  通过/proc/sys/vm/drop_caches这个配置项,我们可以手动清除指定的可回收缓存(SReclaimable)2。

echo 2 > /proc/sys/vm/drop_caches

  上面的命令会主动释放Slab中clean的缓存(包括inode和dentry的缓存),然后再free -g一下,未使用的内存陡增了十几个G。。。
  需要注意的是,手动清除缓存可能会在一段时间内降低系统性能。原则上不推荐这么做,因为如果有需要,系统会自动释放出内存供其他程序使用。
  另外,手动清除Slab缓存是一个治标不治本的办法。因为问题不在Slab,而在于我们那个会引起Slab缓存飙涨的进程(我这里应该是 rsync)。实际操作的时候发现,清除缓存一段时间后,Slab缓存很快又会“反弹”回去。如果需要治本,要么搞定问题进程,要么修改系统配置。
  调整系统vm配置
  风险预警: 调整以下系统配置可能会对系统性能造成负面影响,请仔细测试并谨慎操作。
  /etc/sysctl.conf里有几个对内存管理影响比较大的配置,以下配置项的文档见vm.txt。
  vm.vfs_cache_pressure
  系统在进行内存回收时,会先回收page cache, inode cache, dentry cache和swap cache。vfs_cache_pressure越大,每次回收时,inode cache和dentry cache所占比例越大3。
  vfs_cache_pressure默认是100,值越大inode cache和dentry cache的回收速度会越快,越小则回收越慢,为0的时候完全不回收(OOM!)。


  图片取自The Linux Kernel's VFS Layer
  vm.min_free_kbytes
  系统的"保留内存"的大小,"保留内存"用于低内存状态下的"atomic memory allocation requests"(eg. kmalloc + GFP_ATOMIC),该参数也被用于计算开始内存回收的阀值,默认在开机的时候根据当前的内存计算所得,越大则表示系统会越早开始内存回收。
  min_free_kbytes过大可能会导致OOM,太小可能会导致系统出现死锁等问题。
  vm.swappiness
  该配置用于控制系统将内存swap out到交换空间的积极性,取值范围是[0, 100]。swappiness越大,系统的交换积极性越高,默认是60,如果为0则不会进行交换。
  man proc
  The Linux Kernel's VFS Layer
  The VFS in Linux Kernel V2.4
  openSUSE: System Analysis and Tuning Guide, Chapter 15. Tuning the Memory Management Subsystem
  Red Hat Enterprise Linux, 5.5 Tuning Virtual Memory
  Odd behavior
  Wikipedia:Slab allocation
  Linux System IO Monitoring
  Paging
  Understanding the Linux Virtual Memory Manager
  Understanding the Linux Kernel, 3rd Edition
  1 2
  Red Hat Enterprise Linux,5.1 Checking the Memory Usage,引用于2014-12-12。
  Linux kernel documentation, sysctl#vm,引用于2014-12-12。
  @TODO: 需要查看相关内核代码来确认,不过看vm.txt里的描述应该是这个意思。

相关资源 更多
相关课程 更多

当前位置:

广州 小码王少儿编程 资料详情

本站展示的所有信息内容系由机构或个人用户发布,可能存在发布者所发布的信息,并未获得品牌所有人有效授权。本平台会加强审核,但无法完全排除差错或疏漏。郑重声明:本平台仅为免费注册用户提供免费的信息发布渠道,但不对其发布信息的真实性、准确性和合法性负责,对此也不承担任何法律责任。对于从本网站或本网站的任何有关服务所获得的资讯、内容或广告,您接受或信赖任何信息所产生之风险应自行承担,本网对任何使用或提供本网站信息的商业活动及其风险不承担任何责任。,如果侵犯,请及时通知我们,发送邮件至15610150293@126.com本网站将在第一时间及时删除。