为什么系统Swap变高了

swap用来做什么

缓存和缓冲区属于可回收内存,它们在内存管理中,通常被叫做文件页(File- backed page)大部分文件页都可以直接回收,以后需要时,再从磁盘重新读取就可以了,那些被应用程序修改过,并且暂时没有写入磁盘的数据(脏页)就得先写入磁盘,然后才能进行内存释放

除了文件页外,应用程序动态分配的堆内存叫做匿名页(Anonymous Page)如堆,栈,数据段等,不是以文件形式存在,因此无法和磁盘文件交换,是通过swap机制把不常访问匿名页占用的内存写入到磁盘中,然后释放这些内存,再次方式这些内存时,重新冲磁盘写入内存就可以了

匿名页 和 文件页 的回收都是基于LRU算法,优先回收不常访问的内存,所以LRU维护了active和inactive两个双向链表

  • active:记录活跃内存页
  • inactive:记录不活跃内存页

活跃和非活跃的 匿名页 和 文件页 大小查看

cat /proc/meminfo | grep -i active | sort
Active:           274616 kB
Active(anon):      38224 kB
Active(file):     236392 kB
Inactive:         320624 kB
Inactive(anon):      136 kB
Inactive(file):   320488 kB

swap 原理

Swap就是把一块磁盘空间或者本地文件想做内存来使用,它包括换出和换入两个过程

  • 换出:就是把进程暂时不用的内存数据存储到磁盘中,并且释放这些数据占用的内存
  • 换入:进程再次访问这些内存的时候,把它们从磁盘读取到内存中

使用场景

Swap其实就是把系统的可用内存变大了,即使服务器内存不足,页可用运行大内存的应用程序

  • 内存不足时,有些程序并不想被OOM杀死,而是希望能缓一段时间,等待人工介入或者等系统自动释放其他进程的内容,再分配给它就会用到swap

  • swap也是为了回收匿名页占用的内存

  • 直接内存回收:当有大块内存分配请求,但是内存不足,这时候系统就会回收一部分内存(比如缓存)尽可能的满足新内存的请求,这个过程叫做 直接内存回收

  • 定时内存回收:内核kswapd0线程用来定时回收内存,为了衡量内存的使用情况,kswapd0定义了三个内存阈值是 页最小阈值(pages_min),页低阈值(pages_low)和页高阈值(pages_high),剩余内存则使用pages_free表示

image.png
  • 剩余内存 < 页最小阈值:说明内存可用内存都耗尽了,只有内核才可以分配内存
  • 剩余内存落在页最小阈值页低阈值中间:说明内存使用比较大,剩余内存不多了,kswapd0回执行内存回收,知道剩余内存大于高阈值为止
  • 剩余内存落在页低阈值页高阈值中间:说明内存有一定压力,但是还可以满足新内存请求。
  • 剩余内存 > 页高阈值:说明剩余内存比较对,没有内存压力

页低赋值可以通过内核选项vm.min_free_kbytes 间接设置 /proc/sys/vm/min_free_kbytes,min_free_kbytes设置了页最小阈值,其他两个阈值根据页最小阈值计算生成的

pages_low = pages_min*5/4
pages_high = pages_min*3/2

NUMA与Swap

有时候系统内存剩余还很多,但是Swap还是升高了,是因为处理器NUMA架构导致的

在NUMA框架下,多个处理器被划分到不同Node上,且每个Node 都拥有自己的本地内存空间,并且进一步又分为内内参域(zone),不如 直接内存访问区(DMA),普通内存区(NORMAL),伪内存区(MOVABLE)等

因为NUMA框架下每个Node都有自己的本地内存空间,所以分析内存使用需要根据每个Node单独分析, 可以通过numactl 查看每个Node内存使用情况

[root@master1 ~]# numactl --hardware
available: 1 nodes (0)
node 0 cpus: 0 1 2 3
node 0 size: 8191 MB
node 0 free: 1793 MB
node distances:
node   0
  0:  10

根据这个输出,我们系统中只有一个Node,就是Node0,编号为0 1 2 3的CPU都位于Node0上。另外Node0的内存大小为 8191 MB,剩余1793 MB

前面提到的页最小,页低,页高的三个阈值都可以在内存域/proc/zoneinfo来查看

[root@master1 ~]# cat /proc/zoneinfo | grep -i -A 15 "Node 0"
Node 0, zone      DMA
  pages free     3975
        min      30
        low      37
        high     45
        scanned  0
        spanned  4095
        present  3998
        managed  3977
    nr_free_pages 3975
    nr_alloc_batch 8
    nr_inactive_anon 0
    nr_active_anon 0
    nr_inactive_file 0
    nr_active_file 0
    nr_unevictable 0
--
Node 0, zone    DMA32
  pages free     159434
        min      5530
        low      6912
        high     8295
        scanned  0
        spanned  1044480
        present  782327
        managed  721081
    nr_free_pages 159434
    nr_alloc_batch 1343
    nr_inactive_anon 14605
    nr_active_anon 95179
    nr_inactive_file 193717
    nr_active_file 206850
    nr_unevictable 0
--
Node 0, zone   Normal
  pages free     295068
        min      9798
        low      12247
        high     14697
        scanned  0
        spanned  1310720
        present  1310720
        managed  1277513
    nr_free_pages 295068
    nr_alloc_batch 127
    nr_inactive_anon 16505
    nr_active_anon 141332
    nr_inactive_file 335925
    nr_active_file 383442
    nr_unevictable 0

上面输出包含了三个内存域的指标,min,low,high 就是上面提到的三个内存阈值,而free是剩余内存页数它跟后面的nr_free_pages相同 注意: 这里单位是页,每一页是4kb,比如计算页最小阈值需要把 三个zone的min相加 * 4kb(9798 + 5530 + 30)* 4

根据输入内容发现pages free剩余内存远高于high,所以此时kswapd0不会回收内存,当某个Node内存不足时,系统可以从其他Node寻找空闲内容,页可以从本地内存中回收内存,需要选哪个模式,可以通过/proc/sys/vm/zone_reclaim_mode来调整

  • 默认为0,也就是刚刚提到的模式,表示既可以从其他Node寻找空闲内,页可以从本地回收内存,这时候就会导致回收文件页和匿名页匿名页的回收所以会触发swap
  • 1,2,4,表示只回收本地内存,2表示可以回收写脏数据回收内存,4表示可以用Swap方式回收内存

swappiness

使用swap的积极程度可以通过内核参数 vm.swappiness 间接配置 /proc/sys/vm/swappiness 选项,配置范围0-100,数字越大,越积极使用Swap,也就是更倾向于回收匿名页,数值越小,越消极使用Swap

即使你设置为0,当剩余内存文件页小于高阈值时,还是会发生Swap

# 按VmSwap使用量对进程排序,输出进程名称、进程ID以及SWAP用量
$ for file in /proc/*/status ; do awk '/VmSwap|Name|^Pid/{printf $2 " " $3}END{ print ""}' $file; done | sort -k 3 -n -r | head
dockerd 2226 10728 kB
docker-containe 2251 8516 kB
snapd 936 4020 kB
networkd-dispat 911 836 kB
polkitd 1004 44 kB

总结

Linux通过直接内存回收和定时内存扫描回收方式来释放文件页和匿名页

  • 文件页的回收:就是直接回收缓存,或者把脏数据写回磁盘后释放
  • 匿名也的回收:需要通过Swap换出到磁盘中,下次访问时,在从磁盘换入到内存中

定时内存扫描回收方式的阈值可以通过内核选项vm.min_free_kbytes来设置

只要涉及到回收匿名页就会涉及触发Swap

假如没有开启swap的话,进程的匿名页就无法释放,需要在进程的重启或者杀掉释放

swap使用积极程度可以通过内核参数vm.swappiness 设置

在处理器NUMA框架下,每个Node都有自己的内存域,某个Node自己内存域下剩余内存不多情况下,导致内存回收也就有可能触发Swap

你可能感兴趣的:(为什么系统Swap变高了)