交换分区

Swap交换分区概念

    Linux内核为了提高读写效率与速度,会将文件在内存中进行缓存,这部分内存就是Cache Memory(缓存内存)。即使你的程序运行结束后,Cache Memory也不会自动释放。这就会导致你在Linux系统中程序频繁读写文件后,你会发现可用物理内存变少。当系统的物理内存不够用的时候,就需要将物理内存中的一部分空间释放出来,以供当前运行的程序使用。那些被释放的空间可能来自一些很长时间没有什么操作的程序,这些被释放的空间被临时保存到Swap空间中,等到那些程序要运行时,再从Swap分区中恢复保存的数据到内存中。这样,系统总是在物理内存不够时,才进行Swap交换。

    关于Swap分区,其实我们有很多疑问,如果能弄清楚这些疑问,那么你对Swap的了解掌握就差不多了。如何查看Swap分区大小? Swap分区大小应该如何设置?系统在什么时候会使用Swap分区? 是否可以调整? 如何调整Swap分区的大小?Swap分区有什么优劣和要注意的地方? Swap分区是否必要?那么我一个一个来看看这些疑问吧!

查看Swap分区大小

查看Swap分区的大小以及使用情况,一般使用free命令即可,如下所示,Swap大小为2015M,目前没有使用Swap分区

[root@CatdeXin-PC ~]# free -h
              total        used        free      shared  buff/cache   available
Mem:           1.8G        460M        983M         12M        375M        1.2G
Swap:          2.0G          0B        2.0G

另外我们还可以使用swapon命令查看当前swap相关信息:例如swap空间是swap partition,Swap size,使用情况等详细信息

Swap分区大小设置

系统的Swap分区大小设置多大才是最优呢? 关于这个问题,应该说只能有一个统一的参考标准,具体还应该根据系统实际情况和内存的负荷综合考虑,像ORACLE的官方文档就推荐如下设置,这个是根据物理内存来做参考的。

RAM

Swap Space

Up to 512 MB

2 times the size of RAM

Between 1024 MB and 2048 MB

1.5 times the size of RAM

Between 2049 MB and 8192 MB

Equal to the size of RAM

More than 8192 MB

0.75 times the size of RAM

另外在其它博客中看到下面一个推荐设置,当然我不清楚其怎么得到这个标准的。是否合理也无从考证。可以作为一个参考。

4G以内的物理内存,SWAP 设置为内存的2倍。

4-8G的物理内存,SWAP 等于内存大小。

8-64G 的物理内存,SWAP 设置为8G。

64-256G物理内存,SWAP 设置为16G。

上下两个标准确实也很让人无所适从。我就有一次在一台ORACLE数据库服务器(64G的RAM),按照官方推荐设置了一个很大的Swap分区,但是我发现其实这个Swap几乎很少用到,其实是浪费了磁盘空间。所以如果根据系统实际情况和内存的负荷综合考虑,其实应该按照第二个参考标准设置为8G即可。当然这个只是个人的一些认知。

Swap分区空间什么时候使用

系统在什么情况或条件下才会使用Swap分区的空间呢?
其实是Linux通过一个参数swappiness来控制的。当然还涉及到复杂的算法。

这个参数值可为 0-100,控制系统 swap 的使用程度。高数值可优先系统性能,在进程不活跃时主动将其转换出物理内存。低数值可优先互动性并尽量避免将进程转换处物理内存,并降低反应延迟。默认值为 60。注意:这个只是一个权值,不是一个百分比值,涉及到系统内核复杂的算法。关于该参数请参考这篇文章[转载]调整虚拟内存,在此不做过多赘述。下面是关于swappiness的相关资料

The Linux 2.6 kernel added a new kernel parameter called swappiness to let administrators tweak the way Linux swaps. It is a number from 0 to 100. In essence, higher values lead to more pages being swapped, and lower values lead to more applications being kept in memory, even if they are idle. Kernel maintainer Andrew Morton has said that he runs his desktop machines with a swappiness of 100, stating that "My point is that decreasing the tendency of the kernel to swap stuff out is wrong. You really don't want hundreds of megabytes of BloatyApp's untouched memory floating about in the machine. Get it out on the disk, use the memory for something useful."

Swappiness is a property of the Linux kernel that changes the balance between swapping out runtime memory, as opposed to dropping pages from the system page cache. Swappiness can be set to values between 0 and 100 inclusive. A low value means the kernel will try to avoid swapping as much as possible where a higher value instead will make the kernel aggressively try to use swap space. The default value is 60, and for most desktop systems, setting it to 100 may affect the overall performance, whereas setting it lower (even 0) may improve interactivity (by decreasing response latency.

有两种临时修改swappiness参数的方法,系统重启后失效

swappiness参数的含义和设置

Linux系统一般都需要配置一点swap分区,桌面配置多一点,服务器配置少一点。而对于swap分区的具体使用细节,由一个叫swappiness参数来控制。

swappiness是Linux的一个内核参数,控制系统在进行swap时,内存使用的相对权重。

swappiness参数值可设置范围在0到100之间。 此参数值越低,就会让Linux系统尽量少用swap分区,多用内存;参数值越高就是反过来,使内核更多的去使用swap空间。Ubuntu系统swappiness默认值为60,表示的含义可以这样来理解,当剩余物理内存低于40%(40=100-60)时,开始使用swap分区。CentOS系统此参数的默认值是30。我个人喜欢将作为服务器的Linux系统的swappiness参数设置为10。设置为100可能会影响整体性能,如果内存充足,就可以将这个值设置很低,甚至为0,以避免系统进行swap而影响性能。

swappiness=0究竟意味着什么?

我们都知道,Linux的进程使用的内存分为2种:

  1. file-backed pages(有文件背景的页面,比如代码段、比如read/write方法读写的文件、比如mmap读写的文件,它们有对应的硬盘文件,因此如果要交换,可以直接和硬盘对应的文件进行交换;比如读取一个文件,没有关闭,也没有修改,交换时,就可以将这个文件直接放回硬盘,代码处理其实就是删除这部分内容,只保留一个索引,让系统知道这个文件还处于打开状态,只是它的内容不在内存,还在硬盘上),此部分页面叫做page cache;
  2. anonymous pages(匿名页,如stack,heap,CoW后的数据段等;他们没有对应的硬盘文件,因此如果要交换,只能交换到swap分区),此部分页面,如果系统内存不充分,可以被swap到swapfile或者硬盘的swap分区。

因此,Linux在进行内存回收(memoryreclaim)的时候,实际上可以从1类和2类这两种页面里面进行回收,而swappiness值就决定了回收这2类页面的优先级。swappiness越大,越倾向于回收匿名页;swappiness越小,越倾向于回收file-backed的页面。当然,它们的回收方法都是一样的LRU算法。

在Linux的早期版本(2012年以前的版本,kernel 3.5-rc1),哪怕swappiness被设置为0,其实匿名页仍然有被交换出去的机会。

2012年开始,这个细节有了变化。
参考资料

如果swappiness=0,除非系统的内存过小(nr_free + nr_filebacked < high watermark)这种恶劣情况发生,都只是考虑交换file-backed的pages,就不会考虑交换匿名页了。

于是乎,现在的swappiness如果等于0的话,意味着哪怕匿名页占据的内存很大,哪怕swap分区还有很多的剩余空间,除非恶劣情况发生,都不会交换匿名页,因此这可能造成更大的OOM(Out Of Memory)压力。不像以前,平时会一直兼顾着回收page cache和匿名页。所以,现在如果想将swappiness设置为0,那是要好好想想的了。

如何查看系统当前的swappiness值
[root@CatdeXin-PC ~]# cat /proc/sys/vm/swappiness
30
如何配置swappiness的值
  • 临时性修改两种方法
echo 10 > /proc/sys/vm/swappiness

sudo sysctl vm.swappiness=10
  • 永久性修改两种方法
echo 'vm.swappiness=10' >> /etc/sysctl.conf

// 在/etc/sysctl.conf 文件里添加如下参数:
vm.swappiness=10

Swap交换分区对性能的影响

    我们知道Linux可以使用文件系统中的一个常规文件或独立分区作为Swap交换空间,相对而言,交换分区要快一些。但是和RAM比较而言,Swap交换分区的性能依然比不上物理内存,目前的服务器上RAM基本上都相当充足,那么是否可以考虑抛弃Swap交换分区,是否不需要保留Swap交换分区呢?这个其实是我的疑问之一。在这篇What Is a Linux SWAP Partition, And What Does It Do?博客中,作者给出了swap交换空间的优劣

Advantages:

  1. Provides overflow space when your memory fills up completely
  2. Can move rarely-needed items away from your high-speed memory
  3. Allows you to hibernate

Disadvantages:

  1. Takes up space on your hard drive as SWAP partitions do not resize dynamically
  2. Can increase wear and tear to your hard drive
  3. Does not necessarily improve performance (see below)

其实保留swap分区概括起来可以从下面来看:

首先,当物理内存不足以支撑系统和应用程序(进程)的运作时,这个Swap交换分区可以用作临时存放使用率不高的内存分页,把腾出的内存交给急需的应用程序(进程)使用。有点类似机房的UPS系统,虽然正常情况下不需要使用,但是异常情况下, Swap交换分区还是会发挥其关键作用。

其次,即使你的服务器拥有足够多的物理内存,也有一些程序会在它们初始化时残留的极少再用到的内存分页内容转移到 swap 空间,以此让出物理内存空间。对于有发生内存泄漏几率的应用程序(进程),Swap交换分区更是重要,因为谁也不想看到由于物理内存不足导致系统崩溃。

最后,现在很多个人用户在使用Linux,有些甚至是PC的虚拟机上跑Linux系统,此时可能常用到休眠(Hibernate),这种情况下也是推荐划分Swap交换分区的。

其实少量使用Swap交换空间是不会影响性能,只有当RAM资源出现瓶颈或者内存泄露,进程异常时导致频繁、大量使用交换分区才会导致严重性能问题。另外使用Swap交换分区频繁,还会引起kswapd0进程(虚拟内存管理中, 负责换页的)耗用大量CPU资源,导致CPU飙升。

关于Swap分区的优劣以及是否应该舍弃,我有点恶趣味的想到了这个事情:人身上的两个器官,阑尾和扁桃体。切除阑尾或扁桃体是否也是争论不休。另外,其实不要Swap交换分区,Linux也是可以正常运行的(有人提及过这个问题)

调整Sawp分区的大小

查看Swap的使用情况以及相关信息
[root@CatdeXin-PC ~]# free -h
              total        used        free      shared  buff/cache   available
Mem:           1.8G        463M        979M         12M        376M        1.2G
Swap:          2.0G          0B        2.0G
增加Swap空间 这里增加4G作为示例
[root@CatdeXin-PC ~]# fdisk /dev/sdc
欢迎使用 fdisk (util-linux 2.23.2)。

更改将停留在内存中,直到您决定将更改写入磁盘。
使用写入命令前请三思。

// 创建4G大小的普通空间
命令(输入 m 获取帮助):n
Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p): p
分区号 (1-4,默认 1):
起始 扇区 (2048-10485759,默认为 2048):
将使用默认值 2048
Last 扇区, +扇区 or +size{K,M,G} (2048-10485759,默认为 10485759):+4G
分区 1 已设置为 Linux 类型,大小设为 4 GiB

// 将普通空间文件类型修改为Swap格式
命令(输入 m 获取帮助):t
已选择分区 1
Hex 代码(输入 L 列出所有代码):82
已将分区“Linux”的类型更改为“Linux swap / Solaris”

// 查看效果
命令(输入 m 获取帮助):p

磁盘 /dev/sdc:5368 MB, 5368709120 字节,10485760 个扇区
Units = 扇区 of 1 * 512 = 512 bytes
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:dos
磁盘标识符:0xfbe56044

   设备 Boot      Start         End      Blocks   Id  System
/dev/sdc1            2048     8390655     4194304   82  Linux swap / Solaris

命令(输入 m 获取帮助):w
The partition table has been altered!

Calling ioctl() to re-read partition table.
正在同步磁盘。

[root@CatdeXin-PC ~]# partprobe /dev/sdc

// 设置swap空间
[root@CatdeXin-PC ~]# mkswap /dev/sdc1 
mkswap: /dev/sdc1: warning: wiping old swap signature.
正在设置交换空间版本 1,大小 = 4194300 KiB
无标签,UUID=13c8662d-a22c-41b4-a254-d19045343148

// 挂载swap空间
[root@CatdeXin-PC ~]# swapon /dev/sdc1

// 查看增加后的磁盘空间
[root@CatdeXin-PC ~]# free -h
              total        used        free      shared  buff/cache   available
Mem:           1.8G        466M        976M         12M        376M        1.2G
Swap:          6.0G          0B        6.0G
删除Swap交换分区
swapoff diskPath // 取消交换空间挂载

[root@CatdeXin-PC ~]# swapoff /dev/sdc1
// 可以看到 增加的1G交换分区已经被取消
[root@CatdeXin-PC ~]# free -h
              total        used        free      shared  buff/cache   available
Mem:           1.8G        461M        982M         12M        375M        1.2G
Swap:          2.0G          0B        2.0G

lsblk可以查看硬盘信息

[root@CatdeXin-PC ~]# lsblk
NAME            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda               8:0    0   80G  0 disk
├─sda1            8:1    0    1G  0 part /boot
└─sda2            8:2    0   79G  0 part
  ├─centos-root 253:0    0   50G  0 lvm  /
  ├─centos-swap 253:1    0    2G  0 lvm  [SWAP]
  └─centos-home 253:2    0   27G  0 lvm  /home
sdc               8:32   0    5G  0 disk
└─sdc1            8:33   0    2G  0 part [SWAP]