2.5-内存性能-系统 swap 交换分区

目录

五、系统 swap 分区

5.1 内存回收和 OOM

5.1.1 内存回收

5.1.2 脏页写入磁盘的方式

5.1.3 swap 机制

5.2 Swap 原理

5.2.1 直接内存回收

5.2.2 内核线程进行定期内存回收 —— kswapd0

5.3 NUMA 与 Swap

5.4 swappiness

5.4.1 不同页的内存回收机制

5.5 Swap 使用升高时的定位与分析

5.5.1 案例 —— dd/sar

5.6 总结


五、系统 swap 分区

情景:

1、当发生内存泄露时,或者运行了大内存的应用程序,导致系统的内存资源紧张时,系统要如何应对?

2、内存回收或 OOM 杀死进程

3、当内存资源紧张时,Linux 通过直接内存回收和定期扫描的方式,来释放文件页和匿名页,以便把内存分配给更需要的进程使用

5.1 内存回收和 OOM

  1. OOM 是指系统杀死占用大量内存的进程,释放这些内存,再分配给其他更需要的进程。
  2. 内存回收是系统释放掉可以回收的内存,比如缓存和缓冲区。在内存管理中,叫做文件页。

5.1.1 内存回收

  1. 文件页 —— 缓存和缓冲区
    1. 大部分文件页是可以直接回收,有需要时,再从磁盘重新读取好了。
    2. 被应用程序修改过,并且暂时还没写入磁盘的数据(脏页),得先写入磁盘,然后才能进行内存释放
  2. 匿名页 —— 应用程序动态分配的堆内存
    1. 无法直接释放
    2. 将这些内存通过 Swap 换出先存入磁盘中,然后释放给其他需要的进程

5.1.2 脏页写入磁盘的方式

  1. 在应用程序中,通过系统调用 fsync ,把脏页同步到磁盘
  2. 在系统中,通过内核线程 pdflush 负责这些脏页的刷新

5.1.3 swap 机制

Swap 将这些不常访问的内存先写到磁盘中,然后释放这些内存,给其他更需要的进程使用。再次访问这些内存时,重新从磁盘读取内存就可以了

5.2 Swap 原理

Swap 其实是将一块磁盘空间或一个本地文件,当成内存使用,存在以下两个过程:

  1. 换出
    1. 把进程暂时不用的内存数据存储到磁盘中,并释放这些数据占用的内存
  2. 换入
    1. 在进程再次访问这些内存的时候,把他们从磁盘读取到内存中

5.2.1 直接内存回收

有新的大块内存分配请求,但是剩余内存不足。这个时候系统就需要回收一部分内存(比如前面提到的缓存),进而尽可能地满足新内存请求。

5.2.2 内核线程进行定期内存回收 —— kswapd0

kswapd0水位:

  1. 页最小阈值
  2. 页低阈值
  3. 页高阈值
  4.  pages_free

2.5-内存性能-系统 swap 交换分区_第1张图片

kswapd0 定期扫描内存的使用情况,并根据剩余内存落在这三个阈值的空间位置,进行内存的回收操作。

  • 剩余内存小于页最小阈值,说明进程可用内存都耗尽了,只有内核才可以分配内存。
  • 剩余内存落在页最小阈值和页低阈值中间,说明内存压力比较大,剩余内存不多了。这时 kswapd0 会执行内存回收,直到剩余内存大于高阈值为止。
  • 剩余内存落在页低阈值和页高阈值中间,说明内存有一定压力,但还可以满足新内存请求。
  • 剩余内存大于页高阈值,说明剩余内存比较多,没有内存压力。

5.3 NUMA 与 Swap

情景:

明明发现了 Swap 升高,可是在分析系统的内存使用时,却很可能发现,系统剩余内存还多着呢。为什么剩余内存很多的情况下,也会发生 Swap 呢?

处理器的 NUMA 架构导致

在 NUMA 架构下,多个处理器被划分到不同 Node 上,且每个 Node 都拥有自己的本地内存空间。

#查看处理器在Node 的分布情况
numactl --hardware

页最小阈值、页低阈值和页高阈值,可以通过 /proc/zoneinfo 来查看

cat /proc/zoneinfo
Node 0, zone   Normal
  pages free     363433
        min      9773
        low      12216
        high     14659
        scanned  0
        spanned  5439488
        present  5439488
        managed  5340227
    nr_free_pages 164964

指标说明:

  • pages 处的 min、low、high,就是上面提到的三个内存阈值,而 free 是剩余内存页数,它跟后面的 nr_free_pages 相同

当某个 Node 内存不足时,系统可以从其他 Node 寻找空闲内存,也可以从本地内存中回收内存,具体模式可以通过 /proc/sys/vm/zone_reclaim_mode 来调整。

  • 默认为 0 ,表示既可以从其他 Node 寻找空闲内存,也可以从本地回收内存
  • 1、2、4 都表示只回收本地内存,2 表示可以回写脏数据回收内存,4 表示可以用 Swap 方式回收内存

5.4 swappiness

5.4.1 不同页的内存回收机制

  • 文件页的回收
    • 直接回收缓存,或者把脏页写回磁盘后再回收
  • 匿名页的回收
    • 通过swap机制,把他们写入磁盘后再释放内存

/proc/sys/vm/swappiness 用于调整使用 Swap 的积极程度,swappiness 的范围是0-100,数值越大,越积极使用 Swap,也就更倾向于回收匿名页;数值越小,越消极使用 Swap,也就是更倾向于回收文件页

5.5 Swap 使用升高时的定位与分析

5.5.1 案例 —— dd/sar

Linux 本身支持两种类型的 Swap,即 Swap 分区和 Swap 文件。

# 创建Swap文件
$ fallocate -l 8G /mnt/swapfile
# 修改权限只有根用户可以访问
$ chmod 600 /mnt/swapfile
# 配置Swap文件
$ mkswap /mnt/swapfile
# 开启Swap
$ swapon /mnt/swapfile

模拟大文件的读取:

# 写入空设备,实际上只有磁盘的读请求
$ dd if=/dev/sda1 of=/dev/null bs=1G count=2048

查看内存各个指标的变化情况:

# 间隔1秒输出一组数据
# -r表示显示内存使用情况,-S表示显示Swap使用情况
$ sar -r -S 1
04:39:56    kbmemfree   kbavail kbmemused  %memused kbbuffers  kbcached  kbcommit   %commit  kbactive   kbinact   kbdirty
04:39:57      6249676   6839824   1919632     23.50    740512     67316   1691736     10.22    815156    841868         4

04:39:56    kbswpfree kbswpused  %swpused  kbswpcad   %swpcad
04:39:57      8388604         0      0.00         0      0.00

04:39:57    kbmemfree   kbavail kbmemused  %memused kbbuffers  kbcached  kbcommit   %commit  kbactive   kbinact   kbdirty
04:39:58      6184472   6807064   1984836     24.30    772768     67380   1691736     10.22    847932    874224        20

04:39:57    kbswpfree kbswpused  %swpused  kbswpcad   %swpcad
04:39:58      8388604         0      0.00         0      0.00
…
04:44:06    kbmemfree   kbavail kbmemused  %memused kbbuffers  kbcached  kbcommit   %commit  kbactive   kbinact   kbdirty
04:44:07       152780   6525716   8016528     98.13   6530440     51316   1691736     10.22    867124   6869332         0

04:44:06    kbswpfree kbswpused  %swpused  kbswpcad   %swpcad
04:44:07      8384508      4096      0.05        52      1.27
  • 第一个表格表示内存的使用情况

 

  • 第二个表格表示 Swap 的使用情况

 

  • kb前缀表示这些指标的单位是 KB

指标介绍:

  • kbcommit,表示当前系统负载需要的内存。它实际上是为了保证系统内存不溢出,对需要内存的估计值。%commit,就是这个值相对总内存的百分比。
  • kbactive,表示活跃内存,也就是最近使用过的内存,一般不会被系统回收。
  • kbinact,表示非活跃内存,也就是不常访问的内存,有可能会被系统回收。

现象描述:

  1. 剩余内存(kbmemfree)不断减少,缓存区(kbbuffers)不断增大,可知,剩余内存不断分配给了缓存区
  2. 当剩余内存变小,缓冲区占用了大部分的内存,此时 Swap 的使用(%memused)开始逐渐增大,缓冲区和剩余内存只在小范围内波动
#查看缓存的使用情况
cachetop 5
#观察剩余内存、内存阈值以及匿名页和文件页的活跃情况
/proc/zoneinfo 

# -d 表示高亮变化的字段
# -A 表示仅显示Normal行以及之后的15行输出
$ watch -d grep -A 15 'Normal' /proc/zoneinfo
Node 0, zone   Normal
  pages free     21328
        min      14896
        low      18620
        high     22344
        spanned  1835008
        present  1835008
        managed  1796710
        protection: (0, 0, 0, 0, 0)
      nr_free_pages 21328
      nr_zone_inactive_anon 79776
      nr_zone_active_anon 206854
      nr_zone_inactive_file 918561
      nr_zone_active_file 496695
      nr_zone_unevictable 2251
      nr_zone_write_pending 0

现象:

剩余内存(pages_free)在一个小范围内不停地波动。当它小于页低阈值(pages_low) 时,又会突然增大到一个大于页高阈值(pages_high)的值。

剩余内存和缓冲区的波动变化,正是由于内存回收和缓存再次分配的循环往复。

  • 当剩余内存小于页低阈值时,系统会回收一些缓存和匿名内存,使剩余内存增大。
    • 缓存的回收导致 sar 中的缓冲区减小,而匿名内存的回收导致了 Swap 的使用增大。
  • 由于dd进程还在继续,剩余内存又会重新分配给缓存,导致剩余内存减少,缓冲区增大

5.6 总结

  1. 内存资源紧张时,Linux 通过直接内存回收和定期扫描的方式,来释放文件页和匿名页,以便把内存分配给更需要的进程使用。
  • 文件页回收
    • 直接清空
    • 把脏数据写回磁盘后再释放
  • 匿名页回收
    • Swap 换出磁盘,下次访问时,再从磁盘换入内存
  1. Swap 内存的换入换出
  • 换出
    • 将进程暂时不用的内存数据存储到磁盘中,并释放这些数据占用的内存
  • 换入
    • 在进程再次访问内存时,将他们从磁盘换入到内存中
  1. 调整系统定期回收内存的阈值 —— /proc/sys/vm/min_free_kbytes
  2. 调整文件页和匿名页的回收倾向 —— /proc/sys/vm/swappiness
  3. 当 Swap 变高时,可以用 sar、/proc/zoneinfo、/proc/pid/status 等方法,查看系统和进程的内存使用情况,找出 Swap 升高的根源和受影响的进程
  4. 降低 Swap 的使用,提高系统的整体性能。常见的降低方法:
    1. 禁止 Swap,现在服务器的内存足够大,所以除非有必要,禁用 Swap 就可以了。随着云计算的普及,大部分云平台中的虚拟机都默认禁止 Swap。
    2. 如果实在需要用到 Swap,可以尝试降低 swappiness 的值,减少内存回收时 Swap 的使用倾向。
    3. 响应延迟敏感的应用,如果它们可能在开启 Swap 的服务器中运行,你还可以用库函数 mlock() 或者 mlockall() 锁定内存,阻止它们的内存换出。
#查看使用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

#关闭swap
swapoff -a

#关闭swap再重新打开
swapoff -a && swapon -a

#命令可以直接将进程按照swap使用量排序显示
smem --sort swap

问题:

为什么大部分应用都关闭swap分区?

1、Elasticsearch/JAVA应用

1)Elasticsearch的内存使用情况由JVM控制

2)JVM 的 gc 有关,它在 gc 的时候会遍历所有用到的堆的内存,如果这部分内存是被 swap 出去了,遍历的时候就会有磁盘IO

2、kubernetes

1)性能问题,开启swap会严重影响性能(包括内存和I/O)

2)管理问题,开启swap后通过cgroups设置的内存上限就会失效

3、嵌入式系统

减少写的次数,延长Flash存储的寿命

 

你可能感兴趣的:(内存性能,Linux性能优化)