https://segmentfault.com/a/1190000008125116

每次安装Linux的时候,都会要求配置交换分区,那么这个分区是干嘛的呢?不设置这个分区有什么后果?如果一定要设置,设置多大比较合适?本篇将试图回答这些问题并尽量覆盖所有swap相关的知识。

下面的所有例子都在ubuntu-server-x86_64 16.04下执行通过

##
什么是swap?

swap space是磁盘上的一块区域,可以是一个分区,也可以是一个文件,或者是他们的组合。简单点说,当系统物理内存吃紧时,Linux会将内存中不常访问的数据保存到swap上,这样系统就有更多的物理内存为各个进程服务,而当系统需要访问swap上存储的内容时,再将swap上的数据加载到内存中,这就是我们常说的swap out和swap in。

##
为什么需要swap?

要回答这个问题,就需要回答swap给我们带来了哪些好处。
  • 对于一些大型的应用程序(如LibreOffice、video editor等),在启动的过程中会使用大量的内存,但这些内存很多时候只是在启动的时候用一下,后面的运行过程中很少再用到这些内存。有了swap后,系统就可以将这部分不这么使用的内存数据保存到swap上去,从而释放出更多的物理内存供系统使用。

  • 很多发行版(如ubuntu)的休眠功能依赖于swap分区,当系统休眠的时候,会将内存中的数据保存到swap分区上,等下次系统启动的时候,再将数据加载到内存中,这样可以加快系统的启动速度,所以如果要使用休眠的功能,必须要配置swap分区,并且大小一定要大于等于物理内存

  • 在某些情况下,物理内存有限,但又想运行耗内存的程序怎么办?这时可以通过配置足够的swap空间来达到目标,虽然慢一点,但至少可以运行。

  • 虽然大部分情况下,物理内存都是够用的,但是总有一些意想不到的状况,比如某个进程需要的内存超过了预期,或者有进程存在内存泄漏等,当内存不够的时候,就会触发内核的OOM killer,根据OOM killer的配置,某些进程会被kill掉或者系统直接重启(默认情况是优先kill耗内存最多的那个进程),不过有了swap后,可以拿swap当内存用,虽然速度慢了点,但至少给了我们一个去debug、kill进程或者保存当前工作进度的机会。

  • 如果看过Linux内存管理,就会知道系统会尽可能多的将空闲内存用于cache,以加快系统的I/O速度,所以如果能将不怎么常用的内存数据移动到swap上,就会有更多的物理内存用于cache,从而提高系统整体性能。

##
swap的缺点?

上面介绍了swap的优点,那swap的缺点呢?swap是存放在磁盘上的,磁盘的速度和内存比较起来慢了好几个数量级,如果不停的读写swap,那么对系统的性能肯定有影响,尤其是当系统内存很吃紧的时候,读写swap空间发生的频率会很高,导致系统运行很慢,像死了一样,这个时候添加物理内存是唯一的解决办法。

由于系统会自动将不常用的内存数据移到swap上,对桌面程序来说,有可能会导致最小化一个程序后,再打开时小卡一下,因为需要将swap上的数据重新加载到内存中来。

##
到底要不要swap?

上面介绍了什么是swap以及它们的优缺点,那么到底要不要配置swap呢?答案是:看情况。

下面分别讨论内存不够用、内存勉强够用和内存很充裕这三种情况下服务器和桌面环境对swap的选择。

###
内存不够用

不管是桌面还是服务器,当物理内存明显不够用,而又想跑程序的话,添加swap是唯一的选择,慢点总比不能工作强。

###
内存勉强够用

建议配置swap,这样内核会将不常用的数据从内存移到swap上,从而有更多的物理内存供系统调用,提升系统性能,同时也避免因偶尔的物理内存不够造成进程异常退出,提升系统稳定性,但对服务器来说,一定要限制或者监控swap空间的使用情况,当出现swap空间使用超预期或者swap in/out频繁时,要及时采取措施,不然对性能影响很大

###
内存充裕

理论上来说,如果物理内存足够多并且不需要休眠功能,那swap就没什么用,可关键问题是我们很难保证物理内存在任何情况下都够用,因为总有意想不到的情况发生,比如某些进程耗内存超预期,服务器压力超预期,内存泄漏等。

在内存充裕的这种情况下,如果发生异常,swap能帮到我们吗?

####
桌面环境

一般不会开什么监控功能,所以也没法提前预知内存使用异常,当内存被用光的时候,分两种情况:
  • 配置了swap:在系统变慢的时候能感觉到,可能还有机会杀掉一些进程和保存当前工作进度,当然也会出现慢的想砸电脑的情况,不过在磁盘如此廉价的情况下,浪费点磁盘空间换取这样的一个机会还是值得的。

  • 没有配置swap:内核的OOM killer被触发,可能连保存工作进度的机会都没有。

####
服务器环境

服务器一般都会配置监控程序,当内存用量达到一个阈值的时候告警或者会自动重启异常的进程。但如果没有监控呢?当内存被用光的时候,分两种情况:
  • 配置了swap:这时服务器还能提供服务,但性能会降低好几个档次,直到最终处于几乎死机状态,并且这一过程将持续很长一段时间,对服务器来说是个灾难;所以配置swap只能让服务再苟延残喘一会儿,然后就是长时间的服务中断(比如原来是每秒处理1000个请求的服务器,由于频繁使用swap,导致现在每秒只能处理50个请求,站在系统角度,进程还在运行,但是在业务角度服务已经几乎中断了)。

  • 没配置swap:这时内核的OOM killer被触发,在默认配置下,耗内存的进程会被优先kill掉,这种进程一般就是我们的业务进程,这时守护进程就会自动重启该业务进程(没有守护进程?开什么玩笑),这种情况只会造成服务中断一会会儿(取决于进程重启的时间),不会出现上面因配置了swap而导致性能很差且服务持续中断的情况。就算OOM killer没有kill掉预期的进程,我们通过测试也能发现,然后将OOM killer配置成重启系统,那也比配置了swap在那里苟延残喘的好。

    从上面可以看出,对服务器来说,似乎不配置swap更好,可以让有问题的进程尽快重启,缩短业务受影响的时间。

    并且,就算没有配置监控程序,我们还有cgroups中的内存控制模块,可以控制一组进程所能使用的最大内存数,当超过这个数的时候,可以触发相应的行为,比如重启进程等。

    总的来说,对于桌面环境来说,一般内存没有服务器端那么充裕,并且由于使用场景原因,会打开很多不同类型的GUI窗口,但前台的进程只有一个,大部分都是在后台待命,所以配置swap对提升性能还是有必要的;对于服务器来说,配置的内存都比较充裕,启动起来的进程也都是要干活的进程(不然就不应该被启动起来),并且也没有休眠的需求,再加上有了cgroups之后,可以更轻松的限制进程的内存使用,个人认为配置swap基本没什么必要了,看看coreos,默认就没有swap。

##
swap大小配置多少比较合适?

既然配置swap对桌面系统有帮助,那么配置多少大小的swap比较合适呢?下面是ubuntu给出的建议:
  • 当物理内存小于1G且不需要休眠时,设置和内存同样大小的swap空间即可;当需要休眠时,建议配置两倍物理内存的大小,但最大值不要超过两倍内存大小

  • 当物理内存大于1G且不需要休眠时,建议大小为round(sqrt(RAM)),其中RAM为物理内存大小;当需要休眠时,建议大小是RAM+round(sqrt(RAM)),但最大值不要超过两倍内存大小

  • 如果两倍物理内存大小的swap空间还不够用,建议增加内存而不是增加swap

    下面是详细的不同物理内存情况下的建议,第一列是物理内存的大小,第二列和第三列是不需要和需要休眠两种情况下推荐的大小,第四列是不要超过的最大值

` 物理内存(MB)  不需要休眠  需要休眠  最大值
 256          256       512     512
 512          512       1024    1024
 1024         1024      2048    2048

物理内存(GB)  不需要休眠  需要休眠  最大值
  1          1         2        2
  2          1         3        4
  3          2         5        6
  4          2         6        8
  5          2         7        10
  6          2         8        12
  8          3         11       16
  12         3         15       24
  16         4         20       32
  24         5         29       48
  32         6         38       64
  64         8         72       128
  128        11       139       256`

##
怎么配置swap?

当我们确定好配置多大的swap空间后,具体应该怎么配置呢?当然可以在系统安装的时候分配好,但如果对安装时分配的大小不满意,我们还可以在后面进行调整。在这里将不介绍安装的时候怎么配,只介绍如何往系统中添加更多的swap空间。

Linux下有两种类型的swap空间,swap分区和swap文件,他们有各自的特点:
  • swap分区上面由于没有文件系统,所以相当于内核直接访问连续的磁盘空间,效率相对要高点,但由于swap分区一般安装系统时就分配好了了,后期要缩减空间和扩容都很不方便。

  • swap文件放在指定分区的文件系统里面,所以有可能受文件系统性能的影响,但据说2.6版本以后的内核可以直接访问swap文件对应的物理磁盘地址,相当于跳过了文件系统直接访问磁盘,不过如果swap文件在磁盘上的物理位置不连续时,还是会对性能产生不利影响,但其优点就是灵活,随时可以增加和移除swap文件。

###
查看系统中已经配置的swap

使用命令swapon -s即可查看系统中在用的swap
`dev@dev:~$ swapon -s
Filename                Type        Size    Used    Priority
/dev/dm-1               partition   524284  0       -1`
如果配置有多个swap分区或者文件的话,这里将会有多行,每行代表一个正在被系统使用的swap分区或文件,下面是每个字段的意思:
  • Filename:如果swap类型是分区,这里将是分区的路径,如果swap类型是文件,这里将是文件的路径

  • Type:swap的类型,partition代表这是一个swap分区,file代表这是一个swap文件

  • Size:swap的大小,单位是k,这里524284表示的差不多是512M

  • Used:已经被使用的大小,这里0表示还没有被使用到

  • Priority:优先级,优先级高的swap将会被优先使用,同等优先级的swap将会被均匀的使用(round-robin算法),优先级可以通过“swapon -p”命令来设置

###
查看系统中swap in/out的情况

并不是swap空间占用多就一定性能下降,真正影响性能是swap in和out的频率,频率越高,对系统的性能影响越大,我们可以通过vmstat命令来查看swap in/out的频率
`#参数2表示每两秒统计一次,si和so两列就是每秒swap in和out的次数
dev@ubuntu:~$ 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
 0 0    70232 75620 7940 209476     0  0    0  0    111 180     0  1  99 0  0
 0 0    70232 75620 7940 209476     0  0    0  0    116 186     1  1  99 0  0
 0 0    70228 75620 7940 209476     2  0    2  0    120 193     1  1  98 1  0
 0 0    70228 75620 7940 209476     0  0    0  0    117 186     0  0  100 0 0
 0 0    70228 75620 7940 209476     0  0    0  0    113 184     0  1  99 0  0`

###
 


新建和增加扩容Swap分区

 

方法一、新建磁盘分区作为swap**分区**
在添加swap分区前,首先得有一个空闲的分区,如果是一块新的磁盘,可以用fdisk来创建一个新的分区用于swap。

注意:磁盘分区操作一定要小心,弄不好就会造成数据丢失、系统挂掉的后果。磁盘分区操作不是本篇要介绍的内容,所以这里不会讨论fdisk怎么用。

`#本篇使用的测试环境是虚拟机,/dev/sdb是一块新加的硬盘并且已经用fdisk创建好了一个分区`
`#本例中将使用/dev/sdb1这个分区
 fdisk -l /dev/sdb

#创建swap分区
 mkswap /dev/sdb1

#查看系统中现在正在使用的swap,以便于和添加后做比较
swapon -s`
`#启动新的swap分区
swapon /dev/sdb1

#这时候可以看到新的swap分区已经被加入到系统中了,并且优先级比原来的要低
swapon -s

`
`#为了保证系统重启后会自动加载我们新的swap分区,需要修改/etc/fstab文件
sh -c 'echo "/dev/sdb1 none  swap    sw   0    0" >> /etc/fstab'`
`#查看一下,确保写入成功,这里的第一条是原来的系统的swap分区,第二条是我们刚添加的
grep swap /etc/fstab

`

###
方法二、用文件作为Swap**分区—-常用一些**

添加swap文件就简单多了,也没有分区操作那么有风险。

 

**<span style="color: rgb(51, 51, 51); font-family: 宋体; background-color: inherit;">假设</span>****<span lang="EN-US" style="color: rgb(51, 51, 51); font-family: Verdana, sans-serif; background-color: inherit;">/data<span style="background-color: inherit;">&nbsp;</span></span>****<span style="color: rgb(51, 51, 51); font-family: 宋体; background-color: inherit;">空间大,从</span>****<span lang="EN-US" style="color: rgb(51, 51, 51); font-family: Verdana, sans-serif; background-color: inherit;"><strong style="text-align: left; color: rgb(0, 0, 0); font-family: 微软雅黑; font-size: 14px; font-style: normal; background-color: inherit;"><span lang="EN-US" style="color: rgb(51, 51, 51); font-family: Verdana, sans-serif; background-color: inherit;">data</span>**</span></strong>**<span style="color: rgb(51, 51, 51); font-family: 宋体; background-color: inherit;">里取</span>****<span lang="EN-US" style="color: rgb(51, 51, 51); font-family: Verdana, sans-serif; background-color: inherit;">16G=</span>**<span style="color: rgb(51, 51, 51); line-height: 1.5; font-family: &quot;Helvetica Neue&quot;, Helvetica, Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;WenQuanYi Micro Hei&quot;, &quot;Microsoft Yahei&quot;, sans-serif; background-color: rgb(255, 255, 255);">16384</span>**<span lang="EN-US" style="color: rgb(51, 51, 51); font-family: Verdana, sans-serif; background-color: inherit;">M</span>**

&nbsp;

<span lang="EN-US" style="color: rgb(51, 51, 51); font-family: Verdana, sans-serif; background-color: inherit;">1.</span><span style="color: rgb(51, 51, 51); background-color: inherit;">创建要作为</span><span lang="EN-US" style="color: rgb(51, 51, 51); font-family: Verdana, sans-serif; background-color: inherit;">swap</span><span style="color: rgb(51, 51, 51); background-color: inherit;">分区的文件</span><span lang="EN-US" style="color: rgb(51, 51, 51); font-family: Verdana, sans-serif; background-color: inherit;">:</span><span style="color: rgb(51, 51, 51); background-color: inherit;">增加</span><span lang="EN-US" style="color: rgb(51, 51, 51); font-family: Verdana, sans-serif; background-color: inherit;">16GB</span><span style="color: rgb(51, 51, 51); background-color: inherit;">大小的交换分区,则命令写法如下,其中的</span><span lang="EN-US" style="color: rgb(51, 51, 51); font-family: Verdana, sans-serif; background-color: inherit;">count</span><span style="color: rgb(51, 51, 51); background-color: inherit;">等于想要的块的数量(</span><span lang="EN-US" style="color: rgb(51, 51, 51); font-family: Verdana, sans-serif; background-color: inherit;">bs*count=</span><span style="color: rgb(51, 51, 51); background-color: inherit;">文件大小)。</span>

<font color="#333333" face="Verdana, sans-serif" style="background-color: inherit;">&nbsp;</font><a style="line-height: 1.5; background-color: inherit;"><span lang="EN-US" style="font-family: Verdana, sans-serif; background-color: inherit;"><font color="#ff0000" style="background-color: inherit;">dd if=/dev/zero of=/data/.swapfile bs=4M count=4096</font></span></a>

<span lang="EN-US" style="color: rgb(51, 51, 51); font-family: Verdana, sans-serif; background-color: inherit;"><span style="background-color: inherit;">&nbsp;</span></span><span lang="EN-US" style="color: rgb(51, 51, 51); font-family: Verdana, sans-serif; background-color: white;">&nbsp;</span><span style="color: rgb(51, 51, 51); font-family: Verdana, sans-serif; background-color: white;">&nbsp;</span>

<span lang="EN-US" style="color: rgb(51, 51, 51); font-family: Verdana, sans-serif; background-color: inherit;">2.</span><span style="color: rgb(51, 51, 51); background-color: inherit;">格式化为交换分区文件</span><span lang="EN-US" style="color: rgb(51, 51, 51); font-family: Verdana, sans-serif; background-color: inherit;">:</span>

<span lang="EN-US" style="color: rgb(51, 51, 51); font-family: Verdana, sans-serif; background-color: inherit;"><span style="background-color: inherit;">&nbsp;</span>#</span><span style="color: rgb(51, 51, 51); background-color: inherit;">建立</span><span lang="EN-US" style="color: rgb(51, 51, 51); font-family: Verdana, sans-serif; background-color: inherit;">swap</span><span style="color: rgb(51, 51, 51); background-color: inherit;">的文件系统</span>

<a style="background-color: inherit;"><span lang="EN-US" style="font-family: Verdana, sans-serif; background-color: inherit;"><font color="#ff0000" style="background-color: inherit;">mkswap /data/.swapfile</font></span></a>

&nbsp;

<span lang="EN-US" style="color: rgb(51, 51, 51); font-family: Verdana, sans-serif; background-color: inherit;">3.</span><span style="color: rgb(51, 51, 51); background-color: inherit;">启用交换分区文件</span><span lang="EN-US" style="color: rgb(51, 51, 51); font-family: Verdana, sans-serif; background-color: inherit;">:</span>

<a style="background-color: inherit;"><span lang="EN-US" style="font-family: Verdana, sans-serif; background-color: inherit;"><font color="#ff0000" style="background-color: inherit;">swapon /data/.swapfile</font></span></a>

<span lang="EN-US" style="color: rgb(51, 51, 51); font-family: Verdana, sans-serif; background-color: inherit;"><span style="background-color: inherit;">&nbsp;</span></span>

<span lang="EN-US" style="color: rgb(51, 51, 51); font-family: Verdana, sans-serif; background-color: inherit;"><span style="background-color: inherit;"><span style="text-align: left; color: rgb(51, 51, 51); font-family: 微软雅黑; font-size: 13.5pt; font-style: normal; font-weight: normal; background-color: white;">4用</span><span lang="EN-US" style="text-align: left; color: rgb(51, 51, 51); font-family: Verdana, sans-serif; font-size: 13.5pt; font-style: normal; font-weight: normal; background-color: white;">free</span><span style="text-align: left; color: rgb(51, 51, 51); font-family: 微软雅黑; font-size: 13.5pt; font-style: normal; font-weight: normal; background-color: white;">命令看看</span></span></span>

<span lang="EN-US" style="color: rgb(51, 51, 51); font-family: Verdana, sans-serif; background-color: inherit;"><span style="background-color: inherit;"><span style="text-align: left; color: rgb(51, 51, 51); font-family: 微软雅黑; font-size: 13.5pt; font-style: normal; font-weight: normal; background-color: white;">free -m</span></span></span>

<span lang="EN-US" style="color: rgb(51, 51, 51); font-family: Verdana, sans-serif; background-color: inherit;"><span style="background-color: inherit;"><span style="text-align: left; color: rgb(51, 51, 51); font-family: 微软雅黑; font-size: 13.5pt; font-style: normal; font-weight: normal; background-color: white;">5</span></span><span style="line-height: 1.5; font-family: 微软雅黑; background-color: inherit;">开机时自启用&nbsp;</span></span>

<font color="#333333" style="font-size: 14px; background-color: inherit;">`sh -c <span style="color: rgb(221, 17, 68); background-color: inherit;">&#39;echo &quot;/data/.swapfile &nbsp; &nbsp; swap &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;swap &nbsp; &nbsp;defaults &nbsp; &nbsp; &nbsp; &nbsp;0 0&quot; &gt;&gt; /etc/fstab&#39;</span>`</font>

<span lang="EN-US" style="font: 14px/21px Verdana, sans-serif; text-align: left; color: rgb(51, 51, 51); text-transform: none; text-indent: 0px; letter-spacing: normal; word-spacing: 0px; white-space: normal; font-size-adjust: none; font-stretch: normal; background-color: inherit; -webkit-text-stroke-width: 0px;"><span style="background-color: inherit;"><span style="text-align: left; color: rgb(51, 51, 51); font-family: 微软雅黑; font-style: normal; font-weight: normal; background-color: white;">&nbsp;</span></span></span>

注意:不是所有的文件系统都支持创建swap文件,如btrfs,在btrfs分区里创建swap文件将失败。

###
删除交换空间swap

如果经过深思熟虑之后,确定不再需要swap,那么可以将所有的swap分区和文件从系统中移除,步骤和上面的刚好相反
1 .停掉所有系统正在使用的swap
swapoff /data/.swapfile
或者 swapoff -a

 swapon -s命令没有任何输出,free命令显示swap空间为0,说明swapoff成功
swapon -s
 free -m
 
2.从vi /etc/fstab 中删除项目;否则下次重启后,系统又会重新挂载相应的swap分区和文件
 3. 使用fdiskyast工具或者rm删除分区。
<span style="background-color: inherit;"><span style="background-color: inherit;">rm -rf&nbsp;<span style="background-color: inherit;">/data/.swapfile</span></span></span>

###
 如何优化swap性能?

怎么配置swap可以让它的性能更好呢?
  • 尽量使用swap分区,相对于swap文件来说,分区肯定是连续的物理磁盘空间,而swap文件有可能不是

  • 将swap分区和系统所在的分区放在不同的磁盘上,这样就不会和系统盘抢同一个磁盘的I/O带宽

  • 如果有多块磁盘的话,可以在每个盘上创建一个swap分区,并且将它们的优先级设置的一样,这样内核就会平均的访问这些swap分区,性能相当于原来的N倍(这里N是磁盘的数量)

    不过话又说回来了,如果频繁的访问swap的话,怎么优化swap都没用,跟内存比还是低几个数量级,性能还是下降的厉害,如果不频繁访问swap的话,优化swap又有啥意义呢?所以其实优化swap性能的实际意义不大,这里了解一下就好。

#
配置swappiness

有时我们桌面环境确实配置了比较充裕的内存,并且也配置了swap空间,这个时候就希望尽量减少swap空间的使用,避免对系统性能造成影响,Linux早就帮我们考虑到这种情况了,在2.6内核中,增加了一个叫做swappiness的参数,用于配置需要将内存中不常用的数据移到swap中去的紧迫程度。这个参数的取值范围是0~100,0告诉内核尽可能的不要将内存数据移到swap中,也即只有在迫不得已的情况下才这么做,而100告诉内核只要有可能,尽量的将内存中不常访问的数据移到swap中。

Ubuntu的desktop和server的默认配置都是60(可能会随着版本变化),对于桌面环境来说,界面的响应速度直接关系到系统的流畅程度,如果内存比较充裕的话,可以将这个值设置的小一点,这样就尽可能的把数据留在内存中,从而唤醒后台界面程序会更快一些,Ubuntu desktop建议将该值设置为10,当然大家可以根据swap空间的实际使用情况,任意调整这个参数,直到自己满意的水平为止。对于服务器来说,主要性能衡量标准是整体的处理能力,而不是具体某一次的响应速度,能把更多的内存用来做I/O cache可能效果更好,所以Ubuntu server建议保持60的默认值。
  • 查看当前系统中swappiness的值
`dev@dev:~$ cat /proc/sys/vm/swappiness
60`
  • 修改当前系统中swappiness的值
`dev@dev:~$ sudo sysctl vm.swappiness=10
vm.swappiness = 10
dev@dev:~$ cat /proc/sys/vm/swappiness
10`
上面通过sysctl修改的swappiness值在系统重启后会失效,要想重启后继续生效,需要修改配置文件/etc/sysctl.conf,将下面这行修改成10,如果文件中找不到这行的话,在文件末位加上这行就可以了
`vm.swappiness=10`

##
参考