SWAP 预备知识

前言

SWAP 内存交换分区对大家来说是一个经常被忽视的细节,如果大家对 SWAP 配置不是很熟悉可以参考文章内提到的 Red Hat SWAP SPACE 最佳实践配置链接。本文主要分享 SWAP 的基础知识和优化建议,以及如何使用 ansible 优雅的关闭和增加 SWAP 交换分区等实践心得。

更新历史

2020 年 04 月 27 日 – 初稿

阅读原文 – https://wsgzao.github.io/post/swap/

SWAP 预备知识

什么是 swap

swap 当我们指的名词的时候,它可以是一个分区,也可以是一个文件,是操作系统中一个存放从内存中置换出的数据的地方。 当我们指的是一个动词时候,代表的是从物理内存交换数据到 swap 分区这个动作。

为什么会 swap

  1. 当物理内存不够用时候,会根据特定的算法,把一部分内存交换到 swap 分区(此时还会伴随着高 IO)。但是并不是所有的内存都可以被交换到 swap 分区。
  2. kswapd 进程周期性对内存进行检查,如果发现高于水位线,则触发 swap,此举是为了不让系统剩余内存很少,防止出现突然的大内存申请。这块暂不深入讲解,后续再补充。

swap 的到底是什么

首先我们要知道,内存管理将内存分为 active 和 inactive,进程用户空间使用的映射包括了匿名映射(anon)和文件映射(file)。所有一共有 active anon,inactive anon,active file,inactive file 。对于文件映射,由于本身是磁盘空间中的文件,所有它不会被 swap,当需要释放时候,脏数据直接写回磁盘,其他数据直接释放即可。内存交换到 swap,肯定是交换不活跃的数据,所有,inactive anon 是最主要的被交换的内存。那么对于操作系统来说,当我需要回收内存时候,你说它是针对文件映射好,还是针对匿名映射好,这就涉及到了一个参数:swapiness

swapiness

swapiness 是设置内存回收时候,更倾向于回收文件映射还是匿名映射,在 /proc/sys/vm/swappiness 设置值。对于 swapiness=100,那么两者之间的权重是一致的,值越小,越倾向于回收文件映射,不过如果达到系统高水位线,还是会 swap,除非直接使用 swapoff -a 等手段关闭系统 swap 。

swap 的好坏

swap 的好处是当内存不足时候,可以将一部分交换出去,不会触发 oom-killer 。跑得慢总比不能跑好。 swap 的坏处是交换时候,会触发高 IO,同时会降低系统的性能。对于我们隔离做的不好的时候,会影响到其他应用的性能。

swap 查看方法

一个工具往往具有多种用途,但是本文只说明针对 swap 问题

| 工具名称 | 使用姿势 | 采集指标来源 | | — | — | — | | free | free -h | /proc/meminfo | | top | 按 f,选择 swap | /proc/$pid/smaps | | vmstat | vmstat | /proc/meminfo | | iotop | iotop | | | iostat | iostat -xdm | | | pidstat | pidstat -d 1 | /proc/$pid/io |

# 通过此命令查看内存被哪些进程占用(单位是 MByte )
for i in `cd /proc;ls | grep "^[0-9]" | awk ' $0 >100'` ;do awk '/Swap:/{a=a+$2}END{print '"$i"',a/1024"M"}' /proc/$i/smaps ;done 2>&1 | sort -k2nr | head

3131 102.676M
3127 94.4414M
3136 69.9648M
3129 61.1445M
3097 50.7695M
3086 47.0078M
3119 46.4102M
3106 42.4648M
3094 37.5547M
3092 36.8398M

# 注:以上结果输出 PID 与内存占用大小,通过 PID 可以找到对应进程

常见的 swap 优化思路

以 K8s 为代表的容器编排已经给出了比较简单粗暴的分类

  1. 有状态(Stateful)
  2. 无状态(Stateless)

针对有状态的服务比如 Database 数据库,Cache 缓存等,为了减少核心服务出现 Out of Memory ( OOM )的情况,合理的使用 swap 并做好监控是非常有必要的。

针对无状态的服务比如 K8s,ElasticSearch 等,禁用 swap 的核心原因都是出于性能的考虑,但也需要注意配置内存的限制以及告警策略

Swap Off – why is it necessary?

Set up Elasticsearch » Important System Configuration » Disable swapping

swap 对性能的影响

这是显而易见的,但是还是有必要说的更清楚一点:内存交换 到磁盘对服务器性能来说是 致命 的。想想看:一个内存操作必须能够被快速执行。

如果内存交换到磁盘上,一个 100 微秒的操作可能变成 10 毫秒。再想想那么多 10 微秒的操作时延累加起来。不难看出 swap 对于性能是多么可怕。

最好的办法就是在你的操作系统中完全禁用 swap 。这样可以暂时禁用:

sudo swapoff -a

如果需要永久禁用,你可能需要修改 /etc/fstab 文件,这要参考你的操作系统相关文档。

如果你并不打算完全禁用 swap,也可以选择降低 swappiness 的值。 这个值决定操作系统交换内存的频率。 这可以预防正常情况下发生交换,但仍允许操作系统在紧急情况下发生交换。

对于大部分 Linux 操作系统,可以在 sysctl 中这样配置:

vm.swappiness = 1

swappiness 设置为 1 比设置为 0 要好,因为在一些内核版本 swappiness 设置为 0 会触发系统 OOM-killer (注:Linux 内核的 Out of Memory ( OOM ) killer 机制)。

vm.swappiness 优化

swappiness 的值的大小对如何使用 swap 分区是有着很大的联系的。swappiness=0 的时候表示最大限度使用物理内存,然后才是 swap 空间,swappiness = 100 的时候表示积极的使用 swap 分区,并且把内存上的数据及时的搬运到 swap 空间里面。linux 的基本默认设置为 60,具体如下:

cat /proc/sys/vm/swappiness
60

也就是说,你的内存在使用到 100-60=40%的时候,就开始出现有交换分区的使用。大家知道,内存的速度会比磁盘快很多,这样子会加大系统 io,同时造的成大量页的换进换出,严重影响系统的性能,所以我们在操作系统层面,要尽可能使用内存,对该参数进行调整。

临时调整 swap,这只是临时调整的方法,重启后会回到默认设置的

# 配置
sysctl vm.swappiness=1
# 查看
cat /proc/sys/vm/swappiness
1

永久生效 swap 配置

# 要想永久调整的话,需要将在 /etc/sysctl.conf 修改,加上:
vim /etc/sysctl.conf
vm.swappiness=1
# 刷新生效
sysctl -p

关闭和开启 swap

使用 ansible 实现关闭 swap,config_swap_off.yml

---
- hosts: all
become: yes
gather_facts: no

tasks:
  - name: Disable SWAP in fstab
    replace:
      path: /etc/fstab
      regexp: '^(\s*)([^#\n]+\s+)(\w+\s+)swap(\s+.*)$'
      replace: '#\1\2\3swap\4'
      backup: yes
  - name: Disable SWAP
    shell: |
      swapoff -a

使用 ansible 实现开启 swap,config_swap_on.yml

---
- hosts: all
become: yes
gather_facts: no

tasks:
  - name: Reenable SWAP in fstab
    replace:
      path: /etc/fstab
      regexp: '^#(\s*)([^#\n]+\s+)(\w+\s+)swap(\s+.*)$'
      replace: '\1\2\3swap\4'
  - name: Enable SWAP
    shell: |
      swapon -a

增加 swap

制作 swap 文件

# 创建一个 1G 的文件作为交换分区使用
dd if=/dev/zero of=/opt/swapfile bs=1M count=1000

# 格式化成 swap 分区
mkswap /opt/swapfile

# 打开 swap 分区
swapon /opt/swapfile

# 在 /etc/fstab 中增加一条记录如下
/opt/swapfile   swap   swap defaults 0 0

制作 swap 分区

# 创建一个 swap 分区
fdisk /dev/sdb

# 新建一个分区
n
p
default
default
...
# 修改分区 id 为 swap
t
82
# 写入分区表
w

# 同步内存和分区表信息
partprobe

# 格式化成 swap 分区
mkswap /dev/sdb1

# 打开 swap 分区
swapon /dev/sdb1

# 在 /etc/fstab 中增加一条记录如下
/opt/swapfile   swap   swap defaults 0 0

Tips: 如果本机已有 2G swap 交换分区,又制作了一个 8G 的 swap 分区文件, 那么在执行swapon命令之后, swap 空间将为 10G(swap 空间会累加)

参考文章

Red Hat SWAP SPACE

© 版权声明
THE END
喜欢就支持以下吧
点赞0赞赏
分享
评论 抢沙发

请登录后发表评论