谈谈swap分区
场景
提起swap,很多时候都能看到它的身影,比如:
安装Linux时会提示两个 partition,一个是根目录,另外一个就是 swap(内存置换空间);
安装Kubernetes、Elasticsearch、Tidb......的时候,官方都是建议关闭 swap 分区的。
介绍
认识swap的几个问题:
- swap 是什么?
- swap 的作用?
- swap 的优缺点?
- swap 到底应该关闭还是开启?
swap 是什么?
swap 分区通常被称为交换分区,其实就是一块特殊的硬盘空间,即当实际内存不够用的时候,操作系统会从内存中取出一部分暂时不用的数据,放在交换分区中,从而为当前运行的程序腾出足够的内存空间。
简单说它就是操作系统将物理内存页中的内容拷贝到硬盘上交换空间(Swap Space)以释放内存的过程。
扩展1:什么是虚拟内存?
虚拟内存是操作系统物理内存和进程之间的中间层,它为进程隐藏了物理内存这一概念,通过结合磁盘和内存各自的优势,利用中间层对资源进行更合理地调度充分提高资源的利用率并提供和谐以及统一的抽象。
虚拟内存的优势如下:
- 虚拟内存可以结合磁盘和物理内存的优势为进程提供看起来速度足够快并且容量足够大的存储;
- 虚拟内存可以为进程提供独立的内存空间并引入多层的页表结构将虚拟内存翻译成物理内存,进程之间可以共享物理内存减少开销,也能简化程序的链接、装载以及内存分配过程;
- 虚拟内存可以控制进程对物理内存的访问,隔离不同进程的访问权限,提高系统的安全性;
扩展2:虚拟内存和 swap分区是什么关系?
首先,了解几个概念:
- 物理内存:即随机存取存储器(random access memory,RAM)又称作“随机存储器”,是与CPU直接交换数据的内部存储器,也叫主存(内存)。
- 虚拟内存:若计算机运行程序或操作所需的物理内存(RAM)不足时,会拿一部分磁盘空间来充当内存使用,这部分空间称为虚拟内存。
在Linux系统上虚拟内存称为SWAP分区(通常独立占用一个分区);Windows系统上则称为虚拟内存(可与文件共用一个分区)。
swap的作用?
Linux 中的 Swapping 机制主要是为内存不足和内存闲置两种常见的情况存在的。
-
内存不足:swapping可以将进程中使用相对较少的页面换出内存。当系统需要的内存超过了可用的物理内存时,内核会将内存中不常使用的内存页交换到磁盘上为当前进程让出内存,保证正在执行的进程的可用性;
-
内存闲置:swapping可以将进程中的闲置页面换出内存。应用程序在启动阶段使用的大量内存在启动后往往都不会使用,通过后台运行的守护进程(kswapd),可以将这部分只使用一次的内存交换到磁盘上为其他内存申请预留空间;
swap的优缺点?
优点:
- 利用磁盘的交换空间避免程序因为内存不足而被直接退出,保证服务的可用性。
- 可以释放闲置内存到 swap 上,让系统有更多的物理内存可以使用,一定程度上能提高系统整体性能。
- 系统休眠时会将内存的数据保存到 swap ,以作为『唤醒』主机的状态依据,这样可以加快系统的启动速度。
缺点:
- swap因为是放在磁盘上,磁盘的速度和内存比较起来慢了好几个数量级:
据统计,在 SSD 中随机访问 4KB 数据所需要的时间是访问主存的 1500 倍,机械磁盘的寻道时间是访问主存的 10^5 倍。 - swap会占用磁盘空间,并一定程度加速磁盘的磨损。
目前的硬盘空间越来越大,而且质量也不断提高,所以对于缺点2来说应该问题不大;
而以降低服务质量的代价换取服务的部分可用性,性能才是swap最大的不足之处。
PS: 触发 Swapping 的进程可能会遇到性能损失,同一个页面的频繁换入换出会导致极其明显的性能抖动,如果遇到程序有明显的性能抖动并排查一番无果,试着尝试定位是否是触发了 Swapping。
swap到底应该关闭还是开启?
关于是否应该开启 Swapping 的讨论其实很多,很多人会认为 Swapping 是以前为了解决小内存系统的产物,对于现代的系统来说存在的意义不大。
但存在即合理,我们仍然需要分析场景并利用好 Linux 提供的这一机制。
例如 Kubernetes 要求禁用 Swapping,我们就应该遵循社区提出的建议,在部署 Kubernetes 的机器上关闭这一特性;
在一些桌面系统或者常年上线的服务器,合理的设置 Swapping,可以运行更多的程序,提高程序可用性,在一定程度上还能节约服务器方面的成本。
所以,在讨论 Swapping 到达应不应该开启时,需要根据实际情况实际分析,没有绝对的结论,只有更优的方案。
实践
一些关于swap的常见问题:
- Swap 设置多大好?
- Swap 怎么开关以及查看?
- Swap 触发策略怎么设置好?
- Swap 怎么创建?
- Swap 与 Docker limit的关系?
Swap设置多大好?
有些资料上建议Swap分区的大小设置为物理内存的2倍即可,但这是针对一些桌面系统而言;
在真正的生产环境下,针对运行程序的需要来设置是比较合理的,Swap分区的大小一般可以这样确定:
( 内存大小 + Swap分区大小 ) * 80% = 程序需要占用总内存数
PS: 最大值不要超过两倍内存大小,过多分配可能会导致 Kernel 一直在做内存交换,导致性能下降;过少分配可能导致程序因内存不足而OOM。
Swap 怎么开关以及查看?
- 开关 swap
# 查看交换分区的状态
free -m
# 临时禁用命令,重启失效
swapoff -a
# 临时开启命令,重启失效
swapon -a
# 永久禁用,编辑修改/etc/fstab文件,在swap分区这行前加 # 禁用掉,保存退出
vi /etc/fstab
- 查看系统中在用的swap
# 主要注意Type字段含义:swap的类型,partition代表这是一个swap分区,file代表这是一个swap文件
swapon -s
ashin@guineapig:~$ swapon -s
Filename Type Size Used Priority
/dev/sda5 partition 1911804 0 -2
- 查看系统中swap in/out的情况
#参数2表示每两秒统计一次,si和so两列就是每秒swap in和out的次数
sudo vmstat 2
ashin@guineapig:~$ vmstat 2
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 0 1320288 27248 321180 0 0 304 9 245 110 1 0 88 10 0
0 0 0 1320280 27256 321216 0 0 0 6 308 25 0 0 99 1 0
0 0 0 1320280 27256 321216 0 0 0 0 447 16 0 0 100 0 0
Swap 触发策略怎么设置好?
swappiness
,Linux内核参数,控制换出运行时内存的相对权重。
# 查看方式
cat /proc/sys/vm/swappiness
swappiness参数值可设置范围在0到100之间。低参数值会让内核尽量少用交换,更高参数值会使内核更多的去使用交换空间。
swappiness参数值说明:
- vm.swappiness = 0 仅在内存不足的情况下-当剩余空闲内存低于vm.min_free_kbytes limit时,使用交换空间。
- vm.swappiness = 1 内核版本3.5及以上、Red Hat内核版本2.6.32-303及以上,进行最少量的交换,而不禁用交换。
- vm.swappiness = 10 当系统存在足够内存时,推荐设置为该值以提高性能。
- vm.swappiness = 60 大多数Linux发行版本的默认值。
- vm.swappiness = 100 内核将积极的使用交换空间。
Swap 怎么创建?
swap有两种创建方式:swap分区和swap文件
ps: 使用swap分区比swap文件性能较好。
swap分区:
#1. 新建一个分区(以2G为例)
fdisk /dev/vdb
#2. 将新建的分区创建为swap
mkswap /dev/vdb1
#3. 激活swap分区
swapon /dev/vdb1
#4. 查询已启动的swap
swapon -s
#5. 查询swap分区UUID,将挂载信息写入/etc/fstab,实现swap开机自动挂载
echo "$(blkid |grep swap |awk '{print $2}' | sed 's/"//g') swap swap defaults 0 0" >>/etc/fstab
#6. 挂载swap
mount -a
swap文件:
#1. 创建1G的swap文件
dd if=/dev/zero of=/swapfile bs=1M count=1000
#2. 更改文件为swap
chmod 600 /swapfile
#3. 更改文件属性为swap
mkswap /swapfile
#4. 启用swap
swapon /swapfile
#5. 将swap文件挂载写入/etc/fstab,实现swap开机自动挂载
echo "/swapfile swap swap defaults 0 0" >>/etc/fstab
#6. 挂载swap
mount -a
Swap 与 Docker limit的关系?
当主机开启了 swap ,docker内存限制选项--memory
和--memory-swap
的作用如下:
--memory | --memory-swap | 效果 |
---|---|---|
M | 正数N | 容器最大可用内存为N,其中 ram 为 M,swap 为(N-M),若 N=M 则无可用 swap 资源 |
M | 0 | 相当于未设置 memory-swap |
M | -1 | 容器最大可用内存为 M+主机可用swap |
M | 未设置 | 容器最大可用内存为 2M,其中 ram 为 M,swap 为 M(可使用的 swap 大小跟内存限制的大小一样) |
当主机关闭了 swap ,因为没有可用的swap空间,所以设置--memory-swap
选项是无效的。
总结
即使在内存越来越大的时代,我们仍然不能一刀切说Linux的swap分区没意义,还是得根据实际情况实际分析:
- 不考虑成本时,能加物理内存优先,不使用swap内存;
- 考虑成本时,需要设置合理的swap内存和触发策略,并且对应用性能加监控,防止出现性能抖动带来的问题。
参考
https://www.redhat.com/en/blog/do-we-really-need-swap-modern-systems
https://serverfault.com/questions/881517/why-disable-swap-on-kubernetes
https://draveness.me/whys-the-design-linux-swapping#fn:1