目录
五、系统 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 总结
情景:
1、当发生内存泄露时,或者运行了大内存的应用程序,导致系统的内存资源紧张时,系统要如何应对?
2、内存回收或 OOM 杀死进程
3、当内存资源紧张时,Linux 通过直接内存回收和定期扫描的方式,来释放文件页和匿名页,以便把内存分配给更需要的进程使用
Swap 将这些不常访问的内存先写到磁盘中,然后释放这些内存,给其他更需要的进程使用。再次访问这些内存时,重新从磁盘读取内存就可以了
Swap 其实是将一块磁盘空间或一个本地文件,当成内存使用,存在以下两个过程:
有新的大块内存分配请求,但是剩余内存不足。这个时候系统就需要回收一部分内存(比如前面提到的缓存),进而尽可能地满足新内存请求。
kswapd0水位:
kswapd0 定期扫描内存的使用情况,并根据剩余内存落在这三个阈值的空间位置,进行内存的回收操作。
情景:
明明发现了 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
指标说明:
当某个 Node 内存不足时,系统可以从其他 Node 寻找空闲内存,也可以从本地内存中回收内存,具体模式可以通过 /proc/sys/vm/zone_reclaim_mode 来调整。
/proc/sys/vm/swappiness 用于调整使用 Swap 的积极程度,swappiness 的范围是0-100,数值越大,越积极使用 Swap,也就更倾向于回收匿名页;数值越小,越消极使用 Swap,也就是更倾向于回收文件页
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
指标介绍:
现象描述:
#查看缓存的使用情况
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)的值。
剩余内存和缓冲区的波动变化,正是由于内存回收和缓存再次分配的循环往复。
#查看使用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存储的寿命