20-案例篇:为什么系统的Swap变高了?(下)





前言

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

  1. 文件页的回收比较容易理解,直接清空缓存,或者把脏数据写回磁盘后,再释放缓存就可以了

  2. 匿名页则需要通过Swap换出到磁盘中,这样在下次访问的时候,再次从磁盘换入到内存中就可以了

开启Swap后,可以设置/proc/sys/vm/min_free_kbytes ,来调整系统定期回收内存的阈值
也可以设置 /proc/sys/vm/swappiness ,来调整文件页和匿名页的回收倾向



案例

  1. 环境准备

    # 机器配置:2cpu,4GB内存
    # 预先安装sysstat包
    
    [root@local_sa_192-168-1-6 ~]# cat /etc/redhat-release
    CentOS Linux release 7.9.2009 (Core)
    
    [root@local_sa_192-168-1-6 ~]# uname -r
    5.15.7-1.el7.elrepo.x86_64
    
    [root@local_sa_192-168-1-6 ~]# cat /proc/cpuinfo |grep 'model name'|wc -l
    2
    
    [root@local_sa_192-168-1-6 ~]# free
                  total        used        free      shared  buff/cache   available
    Mem:        4027980      322712     3495244       30236      210024     3467040
    Swap:       8388604           0     8388604
    #### PS
    # 如果没有swap,可以根据以下步骤创建
    # Linux本身支持两种类型的Swap,即Swap分区和Swap文件
    # 以swap文件为例,配置swap文件大小为8GB
    # 1.创建Swap文件
    [root@local_sa_192-168-1-6 ~]# fallocate -l 8G /mnt/swapfile
    
    # 2.修改权限只有root用户可以访问
    [root@local_sa_192-168-1-6 ~]# chmod 600 /mnt/swapfile
    
    # 3. 配置 Swap 文件
    [root@local_sa_192-168-1-6 ~]# mkswap /mnt/swapfile
    正在设置交换空间版本 1,大小 = 8388604 KiB
    无标签,UUID=2187a892-77e1-4dd1-87cd-07c2bfb30c7e
    
    # 4.开启 Swap(如果需要开机启动,则把上面的UUID写入到/etc/fstab表中)
    [root@local_sa_192-168-1-6 ~]# swapon /mnt/swapfile
    
    

  2. 第一个终端中,运行dd命令,模拟大文件的读取

    # 写入空设备,实际上只有磁盘的读请求
    [root@local_sa_192-168-1-6 ~]# dd if=/dev/mapper/centos-root of=/dev/null bs=1G count=2048
    
    

  3. 在第二个终端中运行sar命令,查看内存各个指标的变化情况

    # 间隔1秒输出一组数据
    # -r表示显示内存使用情况
    # -S表示显示Swap使用情况
    [root@local_sa_192-168-1-6 ~]# sar -r -S 1
    16时00分22秒 kbmemfree kbmemused  %memused kbbuffers  kbcached  kbcommit   %commit  kbactive   kbinact   kbdirty
    16时00分23秒    924660   3103320     77.04    819200    138048   4027236     32.43     92360   2859144        20
    
    16时00分22秒 kbswpfree kbswpused  %swpused  kbswpcad   %swpcad
    16时00分23秒   8388604         0      0.00         0      0.00
    
    16时00分25秒 kbmemfree kbmemused  %memused kbbuffers  kbcached  kbcommit   %commit  kbactive   kbinact   kbdirty
    16时00分26秒    115852   3912128     97.12   1403372    134376   4027448     32.44     92772   3675516        20
    
    16时00分25秒 kbswpfree kbswpused  %swpused  kbswpcad   %swpcad
    16时00分26秒   8388604         0      0.00         0      0.00
    .....
    16时00分38秒 kbmemfree kbmemused  %memused kbbuffers  kbcached  kbcommit   %commit  kbactive   kbinact   kbdirty
    16时00分39秒     99832   3928148     97.52   1421212    133728   4026076     32.42     94464   3690748         0
    
    16时00分38秒 kbswpfree kbswpused  %swpused  kbswpcad   %swpcad
    16时00分39秒   8388336       268      0.00         0      0.00
    
    16时00分39秒 kbmemfree kbmemused  %memused kbbuffers  kbcached  kbcommit   %commit  kbactive   kbinact   kbdirty
    16时00分40秒    121456   3906524     96.98   1388452    142876   4029224     32.45     93956   3668408        20
    
    16时00分39秒 kbswpfree kbswpused  %swpused  kbswpcad   %swpcad
    16时00分40秒   8388080       524      0.01       148     28.24
    
    16时00分43秒 kbmemfree kbmemused  %memused kbbuffers  kbcached  kbcommit   %commit  kbactive   kbinact   kbdirty
    16时00分44秒    112616   3915364     97.20   1392340    145424   4028368     32.44     92900   3675456       124
    
    16时00分43秒 kbswpfree kbswpused  %swpused  kbswpcad   %swpcad
    16时00分44秒   8387824       780      0.01       108     13.85
    
    16时00分47秒 kbmemfree kbmemused  %memused kbbuffers  kbcached  kbcommit   %commit  kbactive   kbinact   kbdirty
    16时00分48秒    111288   3916692     97.24   1385396    146108   4032384     32.48     92776   3671704        40
    
    16时00分47秒 kbswpfree kbswpused  %swpused  kbswpcad   %swpcad
    16时00分48秒   8387568      1036      0.01       200     19.31
    
    ##
    sar的输出结果是两个表格,第一个表格表示内存的使用情况,第二个表格表示Swap的使用情况
    各个指标名称前面的kb前缀,表示这些指标的单位是KB
    ##
    kbcommit,表示当前系统负载需要的内存。它实际上是为了保证系统内存不溢出,对需要内存的估计值
    %commit,就是这个值相对总内存的百分比
    ##
    kbactive,表示活跃内存,也就是最近使用过的内存,一般不会被系统回收
    kbinact,表示非活跃内存,也就是不常访问的内存,有可能会被系统回收
    ##
    从输出结果可以看到,总的内存使用率(%memused)在不断增长,从开始的77%一直长到了97%
    并且主要内存都被缓冲区(kbbuffers)占用
    剩余内存(kbmemfree)不断减少,而缓冲区(kbbuffers)则不断增大
    由此可知,剩余内存不断分配给了缓冲区
    一段时间后,剩余内存已经很小,而缓冲区占用了大部分内存
    这时候,Swap的使用开始逐渐增大,缓冲区和剩余内存则只在小范围内波动
    ##
    为什么缓冲区在不停增大?这又是哪些进程导致的呢?
    
    

  4. cachetop看看进程缓存的情况

    [root@local_sa_192-168-1-6 ~]# cachetop 5
    17:15:02 Buffers MB: 2254 / Cached MB: 201 / Sort: HITS / Order: descending
    PID      UID      CMD              HITS     MISSES   DIRTIES  READ_HIT%  WRITE_HIT%
        1664 root     dd                 370541   397312        0	   48.3%      51.7%
        1667 root     cachetop                2        0        0     100.0%       0.0%
        
    ##
    通过cachetop的输出,dd进程的读写请求只有50%的命中率,并且未命中的缓存页数(MISSES)为 397312(单位是页)
    这说明,正是案例开始时运行的dd,导致了缓冲区使用升高
    ##
    为什么Swap也跟着升高了呢?缓冲区占了系统绝大部分内存,还属于可回收内存,内存不够用时,不应该先回收缓冲区吗?
    
    

  5. 观察/proc/zoneinfo文件

    # -d 表示高亮变化的字段
    # -A 表示仅显示 Normal 行以及之后的 15 行输出
    [root@local_sa_192-168-1-6 ~]# watch -d grep -A 15 'Normal' /proc/zoneinfo
    Every 2.0s: grep -A 15 Normal /proc/zoneinfo                                                                                        Mon Dec 13 17:31:03 2021
    
    Node 0, zone   Normal
      pages free     2311
            min	 1905
            low	 2381
            high     2857
            spanned  131072
            present  131072
            managed  112791
            cma	 0
            protection: (0, 0, 0, 0, 0)
          nr_free_pages 2311
          nr_zone_inactive_anon 38892
          nr_zone_active_anon 186
          nr_zone_inactive_file 20503
          nr_zone_active_file 21185
          nr_zone_unevictable 384
          
    ##
    可以发现,剩余内存(pages_free)在一个小范围内不停地波动。
    当它小于页低阈值(pages_low)时,又会突然增大到一个大于页高阈值(pages_high)的值
    ##
    再结合刚刚用sar看到的剩余内存和缓冲区的变化情况
    可以推导出剩余内存和缓冲区的波动变化,正是由于内存回收和缓存再次分配的循环往复
    1. 当剩余内存小于页低阈值时,系统会回收一些缓存和匿名内存,使剩余内存增大
    其中,缓存的回收导致sar中的缓冲区减小,而匿名内存的回收导致了Swap的使用增大
    2.紧接着,由于dd还在继续,剩余内存又会重新分配给缓存,导致剩余内存减少,缓冲区增大
    
    

  6. 查看 swappiness 的配置

    [root@local_sa_192-168-1-6 ~]# cat /proc/sys/vm/swappiness
    60
    ##
    swappiness显示的是默认值60,这是一个相对中和的配置
    所以系统会根据实际运行情况,选择合适的回收类型,比如回收不活跃的匿名页,或者不活跃的文件页
    
    

  7. 查看使用 Swap 最多的进程

    # 安装smem包 
    [root@local_sa_192-168-1-6 ~]# yum install smem -y
    #
    [root@local_sa_192-168-1-6 ~]# smem --sort swap
      PID User     Command                         Swap      USS      PSS      RSS
        1 root     /usr/lib/systemd/systemd --        0     2760     2859     4956
      539 root     /usr/lib/systemd/systemd-jo        0     1240     1729     4096
      566 root     /usr/sbin/lvmetad -f               0     2752     2909     5312
      575 root     /usr/lib/systemd/systemd-ud        0     1788     1868     3960
     1134 www      php-fpm: pool www               1116      208      246     9580
     1135 www      php-fpm: pool www               1116      208      246     9580
     1136 www      php-fpm: pool www               1116      208      246     9580
     1507 root     /usr/bin/sudo -E LD_LIBRARY     1164       12      494     6192
     1599 root     /usr/bin/sudo -E LD_LIBRARY     1168       40      512     6212
     1632 root     /usr/bin/sudo -E LD_LIBRARY     1168        8      501     6200
    
    


小结

在内存资源紧张时,Linux 会通过Swap ,把不常访问的匿名页换出到磁盘中,下次访问的时候再从磁盘换入到内存中来
可以设置 /proc/sys/vm/min_free_kbytes,来调整系统定期回收内存的阈值
也可以设置 /proc/sys/vm/swappiness,来调整文件页和匿名 页的回收倾向

当Swap变高时,可以用sar、/proc/zoneinfo、/proc/pid/status等方法
查看系统和进程的内存使用情况,进而找出Swap升高的根源和受影响的进程

降低Swap的使用,可以提高系统的整体性能的几种常见方法

  1. 禁止Swap,现在服务器的内存足够大,所以除非有必要,禁用Swap就可以了
    随着云计算的普及,大部分云平台中的虚拟机都默认禁止Swap
  2. 如果实在需要用到Swap,可以尝试降低swappiness的值,减少内存回收时Swap的使用倾向
  3. 响应延迟敏感的应用,如果它们可能在开启Swap的服务器中运行
    还可以用库函数mlock()或者mlockall()锁定内存,阻止它们的内存换出

上一篇:flutter 嵌套滑动实现


下一篇:视频监控存储的计算