Linux上的内存丢失 - 没有缓存,不是缓冲区

Dav*_*get 11 linux memory-management zfs lxc

我的Ubuntu 12服务器神秘地丢失/浪费内存.它有64GB的内存.即使我关闭了所有应用程序,也会显示大约46GB.不报告此内存用于缓冲区或缓存.

顶部的结果(我的应用程序正在运行;应用程序使用大约9G):

top - 21:22:48 up 46 days, 10:12,  1 user,  load average: 0.01, 0.09, 0.12
Tasks: 635 total,   1 running, 633 sleeping,   1 stopped,   0 zombie
Cpu(s):  0.2%us,  0.2%sy,  0.0%ni, 99.6%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:  65960100k total, 55038076k used, 10922024k free,   271700k buffers
Swap:        0k total,        0k used,        0k free,  4860768k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                                                                                         
  5303 1002      20   0 26.2g 1.2g  12m S    0  1.8   2:08.21 java                                                                                                                                             
  5263 1003      20   0  9.8g 995m 4544 S    0  1.5   0:19.82 mysqld                                                                                                                                           
  7021 www-data  20   0 3780m  18m 2460 S    0  0.0   8:37.50 apache2                                                                                                                                          
  7022 www-data  20   0 3780m  18m 2540 S    0  0.0   8:38.28 apache2      
  .... (smaller processes)
Run Code Online (Sandbox Code Playgroud)

请注意,top报告4.8G用于缓存,而不是48G,并且它使用的是55G.free -m的结果:

             total       used       free     shared    buffers     cached
Mem:         64414      53747      10666          0        265       4746
-/+ buffers/cache:      48735      15678
Swap:            0          0          0
Run Code Online (Sandbox Code Playgroud)

什么在用我的记忆?我已经尝试了每一种我都能遇到的诊断.论坛淹没了人们问同样的问题,因为Linux正在使用他们的RAM用于缓冲区/缓存.这似乎不是这里发生的事情.

系统是lxc容器的主机可能是相关的.上面报告的最高和免费结果来自主机,但容器内报告了类似的内存使用情况.停止所有容器不会释放内存.一些46G仍在使用中.但是,如果我重新启动主机,内存是免费的.它不会在一段时间内达到46G.(我不知道是否需要数天或数周.这需要几个小时.)

系统使用zfs也可能是相关的.Zfs在内存方面很受欢迎,但并不是那么多.该系统在两个raidz池上有两个zfs文件系统,一个是1.5T,另一个是200G.我有另一台服务器,它表现出完全相同的问题(没有使用46G)并且配置非常相同,但使用3T阵列而不是1.5T.我为每个zfs文件系统提供了大量快照(大约100个).我通常有一个随时安装的每个文件系统的快照.卸下那些并没有让我回忆起我的记忆.

我可以看到上面屏幕截图中的VIRT数字大致与使用的内存大致相符,但即使在我关闭运行它们的容器后,即使我关闭这些应用程序后内存仍然使用.

编辑:我尝试添加一些交换,发生了一些有趣的事情.我添加了30G的交换.片刻之后,标记为缓存在顶部的内存量从5G增加到25G.Free -m表示大约20G可用内存.我添加了另外10G的交换,并将缓存的内存提升到33G.如果我添加另一个10G的交换,我会将6G更多地识别为缓存.一直以来,只报告使用了几千字节的交换.就好像内核需要为它识别或报告为缓存的每个位都有匹配的交换.这是40G交换顶部的输出:

top - 23:06:45 up 46 days, 11:56,  2 users,  load average: 0.01, 0.12, 0.13
Tasks: 586 total,   1 running, 585 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:  65960100k total, 64356228k used,  1603872k free,   197800k buffers
Swap: 39062488k total,     3128k used, 39059360k free, 33101572k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                                                                                         
 6440 1002      20   0 26.3g 1.5g  11m S    0  2.4   2:02.87 java                                                                                                                                             
 6538 1003      20   0  9.8g 994m 4564 S    0  1.5   0:17.70 mysqld                                                                                                                                           
 4707 dbourget  20   0 27472 8728 1692 S    0  0.0   0:00.38 bash      
Run Code Online (Sandbox Code Playgroud)

任何建议高度赞赏.

编辑2:这是来自/ proc/spl/kstat/zfs/arcstats的arc*值

arc_no_grow                     4    0
arc_tempreserve                 4    0
arc_loaned_bytes                4    0
arc_prune                       4    0
arc_meta_used                   4    1531800648
arc_meta_limit                  4    8654946304
arc_meta_max                    4    8661962768
Run Code Online (Sandbox Code Playgroud)

ZFS没有激活L2ARC

jll*_*gre 14

ZFS ARC缓存和存储在内核内存中的其他ZFS相关数据很可能使用此内存.ARC缓存有点类似于缓冲区缓存,所以通常没有什么可担心的,因为如果需要它,ZFS会释放这个内存.

但是,缓冲区缓存和ARC缓存之间存在细微差别.第一个可立即分配,而ARC缓存则不可分配.ZFS监视可用的可用RAM,当它太低时,它会向其他用户释放RAM.

这适用于大多数应用程序,但是当报告少量可用RAM时,它们中的一小部分要么混淆,要么为发布过程分配太多/太快的内存以正确地保持速度.

这就是为什么ZFS允许减小允许使用ARC大小的最大大小的原因.此设置在/etc/modprobe.d/zfs.conf文件中完成.

例如,如果您希望ARC永远不会超过32 GB,请添加以下行:

options zfs zfs_arc_max=34359738368
Run Code Online (Sandbox Code Playgroud)

要获取当前ARC大小和各种其他ARC统计信息,请运行以下命令:

cat /proc/spl/kstat/zfs/arcstats
Run Code Online (Sandbox Code Playgroud)

size指标将显示ARC的当前大小.请注意,其他与ZFS相关的内存区域也可能占用RAM的份额,即使不再使用也不一定能快速释放.最后,Linux上的ZFS比Solaris本地执行肯定不太成熟,所以你可能会被这样的错误被击中一个.

另请注意,由于共享存储池设计,卸载ZFS文件系统不会释放任何资源.您需要导出池以便最终释放内存.