What You See Is What You Get Element

使用交换监视和使用 ZFS 卷扩大交换空间

适用于 Oracle Solaris 11.1

作者:Alexandre BorgesOracle ACE

本文是系列文章的第 2 部分,介绍 Oracle Solaris 11.1 中 ZFS 的关键特性,并提供分步过程说明如何使用这些特性。本文介绍如何监视交换空间以及如何使用 ZFS 卷扩大或缩小交换空间。


2014 年 4 月发布


右箭头 第 1 部分 — 使用 COMSTAR 和 ZFS 配置虚拟化存储环境
右箭头 第 2 部分 — 使用交换监视和使用 ZFS 卷扩大交换空间
右箭头 第 3 部分 — 使用 ZFS 影子迁移
右箭头 第 4 部分 — 将 ZFS 数据集委托给非全局区域
右箭头 第 5 部分 — 使用 ZFS 加密
右箭头 第 6 部分 — 使用 ZFS 快照

安装过程中,Oracle Solaris 11 通常将交换空间设置为约四分之一 RAM 大小。每种环境的系统(特别是应用)要求各不相同,因此通常需要添加或删除空间来修改交换空间大小。

想对本文发表评论吗?请将链接发布在 Facebook 的 OTN Garage 页面上。有类似文章要分享?请将其发布在 Facebook 或 Twitter 上,我们来进行讨论。

交换空间是磁盘上的一个专用区域,用于存储因 RAM 空间不够而移出的分页匿名内存和进程。

监视交换空间

查看系统上当前空间交换大小的办法有多种,例如:

root@solaris11-1:~# swap -l
swapfile                     dev  swaplo    blocks     free
/dev/zvol/dsk/rpool/swap   285,2       8   2097144  2097144

其中:

  • swapfile 指示来自 /dev/zvol/dsk/rpool/swap 中的 ZFS 卷的交换空间。
  • dev 显示主设备号,本例中确认了交换对象确系基于 ZFS 卷:

    root@solaris11-1:~# more /etc/name_to_major | grep 285
    zfs 285
    
  • swaplo 指示可能的最低交换空间大小,它代表内存页大小(8 扇区 x 512 字节 = 4K)。要查看此大小,可执行以下命令获得 pagesize

    root@solaris11-1:~# pagesize
    4096
    

    Intel 计算机上此值通常为 4K。但对于 SPARC 计算机上的 Oracle Solaris 11,页面大小可能在 16K 至 2 GB 之间(此上限也适用于 Intel 处理器)。此上限主要用作系统全局区域 (SGA) 的页面大小,SGA 是 Oracle Database 11g 实例的专用共享内存区域。此外,值得注意的是,Oracle Solaris 10 8/11 或更高的 Oracle Solaris 版本和 Oracle SPARC T4 处理器支持 2 GB 页面,但默认情况下不启用此页面大小。如果此页面大小适合某些应用,我们必须在 /etc/system 文件中插入 set max_uheap_lpsize=0x80000000,然后重新启动系统来启用它。

    而且,Oracle Solaris 11 支持多种页面大小,可根据应用配置文件手动设置,或者通过新的内置内存预测技术(它能够分析应用需求,分配一个合适的值)自动设置。

    运行以下命令(本例中是在 Intel 处理器上)可显示受支持的页面大小:

    root@solaris11-1:~# pagesize -a
    4096
    2097152
    

    以上示例显示支持两种页面大小:4K 和 2 GB。使用更大的内存页面的真实原因是通过减少 TLB(转换后备缓冲区)未命中次数提高内存管理单元 (MMU) 性能。可以使用 trapstat 命令(虽然 trapstat 通常不会在 Intel 平台上实现)验证 TLB 未命中次数。

  • blocks 是交换空间的总大小(2097144 x 512 字节 = 1 GB)。
  • free 代表空闲交换空间 (1 GB)。

以下命令是监视交换空间的另一个好办法:

root@solaris11-1:~# swap -s
total: 680180k bytes allocated + 266516k reserved = 946696k used, 2321756k available

从命令输出可以看到以下内容:

  • 680180K bytes allocated 表示已经使用(即以前分配过但此时并不一定仍在使用)以及继续可用和保留的交换空间量。大致相当于上限阈值。
  • 266516k reserved 表示尚未分配但已声明供将来可能的使用的交换空间。记住,在为进程创建虚拟内存(堆段或匿名内存)时保留交换空间,然后在进程运行时分配保留的交换空间。组成匿名内存 的页面要么在任何文件系统中均无对应物,要么因物理内存 (RAM) 不足 — 可能是因为堆栈、共享内存和进程堆(例如来自 malloc 函数)大于可用内存量 — 而迁移到交换空间。
  • 946696k used 表示分配或保留的交换空间总量。
  • 2321756k available 表示可用于将来分配的交换空间。

此外,我们还必须记住,在为进程创建虚拟内存时保留了一些交换空间,但此保留空间只有一部分真正与该进程的地址空间关联;否则,可能会错误地解释 swap -s 输出,因为它指示最终保留了(为了分配空间,必须先保留空间)946696k,而已分配的交换空间是 680180K。

另一个要点是 swap -l 命令报告(磁盘上的)物理交换空间,而 swap -s 报告虚拟交换空间,是物理交换空间和物理内存之和。因此,swap -s 报告的可用交换空间是空闲 物理交换空间加空闲 物理内存空间之和。因此,不建议使用 swap -s 命令估算物理交换空间;而应使用 swap -l

如果我们要尝试其他办法获取交换信息,可以使用 echo ::swapinfo | mdb -k 命令,例如:

root@solaris11-1:~# echo ::swapinfo | mdb -k
            ADDR            VNODE     PAGES      FREE NAME
ffffc10007798260 ffffc10007a7db40    262143    262143 /dev/zvol/dsk/rpool/swap

确认 262143 页 x 8K = 2097144K 很简单。

如前所述,最好记住匿名内存在文件系统中没有对应物。通常,匿名页面是进程的私有数据,包括进程堆(匿名数据)和线程结构(如堆栈区域)。

交换 — 交换程序进程 (sched) 的一个操作,换出睡眠超过 20 秒的进程(先是线程结构,然后是堆栈和堆数据 [匿名页面]) — 不应与分页 混淆,分页将页面(通常每页 4 KB 或 8 KB)从内存移到磁盘,通常可实现极高的内存管理效率。但是,有一种分页会严重影响系统性能 — 匿名分页(主要是匿名页面调入),因为它会增加从磁盘读回数据的应用延迟。

而且,不应将交换与回收 (reaping) 混淆,后者是从内核 slab 分配器缓存释放内存的技术,由函数 kmem_reap( ) 执行。

如何验证系统是否使用匿名页?在以下输出中,主要关注 apo(匿名页面调出)和 api(匿名页面调入)列,理想情况下,这两列均应等于 0。后者导致应用延迟增加。

root@solaris11-1:~# vmstat -p 1
     memory           page          executable      anonymous      filesystem
   swap      free  re  mf  fr  de  sr  epi  epo  epf  api  apo  apf  fpi  fpo  fpf
 2973844  2609240   3 18   0   0   3    0    0    0    0    0    0    0    0    0
 2895156  2544236  26 47   0   0   0    0    0    0    0    0    0    0    0    0
 2895156  2544092   0  0   0   0   0    0    0    0    0    0    0    0    0    0

要查明哪个进程在执行匿名页面调入,请使用以下命令:

root@solaris11-1:~# dtrace -n 'vminfo:::anonpgin { @[pid, execname] = count(); }'

大量页面扫描(搜索空闲内存页)表明分页释放的内存不足以应用需求,此时,交换是最后的手段。

通常,当空闲内存量低于 desfree 内核参数指定的数量和 minfree 内核参数指定的数量时,页面扫描会变得更加频繁。如果空闲内存量持续低于 desfree 值至少 30 秒,系统将启动交换。

最糟糕的交换形式是硬交换,即卸载某些不活动的内核模块并将其移到交换空间。

可以使用以下命令监视系统是否在进行硬交换:

root@solaris11-1:~# echo "hardswap/D" | mdb -k
hardswap:
hardswap:       0

硬交换极少发生,因为它必须满足以下条件:

  • 空闲内存量必须低于 desfree 至少 30 秒,且
  • 运行队列(下面的 vmstat 输出中的 r 列)中必须始终有两个待处理的进程,且
  • freemem 必须低于 minfree,或者页面调入数加页面调出数必须大于 maxpgio,其中 maxpgio 是分页系统能够排入队列中的页面调出请求数。

换句话说,maxpgio 用于限制在不导致磁盘 I/O 瓶颈的情况下可以发送到交换的内存页数。因此,maxpgio 基于使用自己的磁盘控制器的交换设备数。其默认值为 40 页。

更常见的是一种名为软交换 的轻型交换,发生在空闲内存量低于 desfree 值时。

执行以下命令可以检查软交换:

root@solaris11-1:~# echo "softswap/D" | mdb -k
softswap:
softswap:       0  

简单介绍一下(更多详情不在本文范围内),minfree 值等于 desfree/2,desfree 值等于 lotsfree/2。以下是计算 lotsfree 的公式:

lotsfree = [memory - kernel]/(64 * page size)]

运行以下命令可以看到这些值:

root@solaris11-1:~# prtconf | grep -i memory
Memory size: 4096 Megabytes

root@solaris11-1:~# echo lotsfree/D | mdb -k
lotsfree:
lotsfree:       16318  

root@solaris11-1:~# echo desfree/E | mdb -k
desfree:
desfree:        8159       
     
root@solaris11-1:~# echo minfree/D | mdb -k
minfree:
minfree:        4079        
    
root@solaris11-1:~# bc
16318 * 4096 * 64
4277665792
root@solaris11-1:~#

获取 lotsfreedesfreeminfree 值的最好办法是执行以下命令:

root@solaris11-1:~# kstat -n system_pages
module: unix                            instance: 0     
name:   system_pages                    class:    pages
        availrmem                       409132
        crtime                          0
        desfree                         8159
        desscan                         25
        econtig                         4229439488
        fastscan                        522183
        freemem                         243665
        kernelbase                      0
        lotsfree                        16318
        minfree                         4079
        nalloc                          110633425
        nalloc_calls                    31285
        nfree                           107403292
        nfree_calls                     23611
        nscan                           0
        pagesfree                       243665
        pageslocked                     635234
        pagestotal                      1044366
        physmem                         1044366
        pp_kernel                       649290
        slowscan                        100
        snaptime                        26017.87927546

回到页面扫描的话题,对于在不同时间发生的页面扫描,有不同的值。例如,fastscan 是空闲内存等于 0 时每秒扫描的页面数,desscan 是页面扫描期间的扫描速度目标,nscan 是上次页面扫描操作期间扫描的页面数。在本例中,内存充足,没有任何页面扫描活动(nscan 等于 0)。

运行以下命令可从 kstat 收集到相同的信息:

root@solaris11-1:~# echo fastscan/E | mdb -k
fastscan:
fastscan:       522183          
root@solaris11-1:~# echo slowscan/E | mdb -k
slowscan:
slowscan:       100             
root@solaris11-1:~# echo desscan/E | mdb -k
desscan:
desscan:        25              
root@solaris11-1:~# echo nscan/E | mdb -k
nscan:
nscan:          0               

要监视交换空间,可以执行以下命令检查过去和当前(实时)的交换统计信息:

root@solaris11-1:~# vmstat 1
 kthr      memory            page            disk          faults      cpu
 r b w    swap    free  re  mf pi po fr de sr s0 s2 s3 s4   in   sy   cs us sy id
 0 0 0 2972960 2608516   3  18  0  0  0  0  3  0  0  0  0  659  480  723  1  4 95
 0 0 0 2895104 2544208  26  49  0  0  0  0  0  0  0  0  0  660  648  694  1  4 95
 0 0 0 2895104 2544056   0   2  0  0  0  0  0  0  0  0  0  690 1839  847  4  4 92

对我们而言,重要的是 w 列,当空闲内存量降至低于 minfreedesfree 超过 30 秒时,需要将空闲进程换出到交换空间,该列显示由此可能产生的内存压力导致换出的线程。

以下命令显示实时交换状态:

root@solaris11-1:~# vmstat -S 1
 kthr      memory            page            disk          faults      cpu
 r b w   swap     free  si  so pi po fr de sr s0 s2 s3 s4   in   sy   cs us sy id
 0 0 0 2972572 2608200   0   0  0  0  0  0  3  0  0  0  0  659  480  723  1  4 95
 0 0 0 2895032 2544000   0   0  0  0  0  0  0  0  0  0  0  706  875  901  2  5 93
 0 0 0 2895032 2544000   0   0  0  0  0  0  0  0  0  0  0  615  511  671  1  3 96

sosi 列分别表示实时换出页和换入页。同样,理想情况下,为取得良好性能,二者均应为 0。

使用 ZFS 卷添加或删除交换空间

我们已经知道如何监视交换空间,下面来了解如何添加和删除分配给交换区域的磁盘空间。我们使用的 Oracle Solaris 11 主机 (solaris11-1) 具有以下文件系统相关的组件:

root@solaris11-1:~# zfs list -r rpool
NAME                              USED  AVAIL  REFER  MOUNTPOINT
rpool                            28.5G  49.7G  4.91M  /rpool
rpool/ROOT                       25.4G  49.7G    31K  legacy
rpool/ROOT/solaris               25.4G  49.7G  24.4G  /
rpool/ROOT/solaris-backup-1       138K  49.7G  24.2G  /
rpool/ROOT/solaris-backup-1/var    64K  49.7G   291M  /var
rpool/ROOT/solaris/var            486M  49.7G   234M  /var
rpool/VARSHARE                     92K  49.7G    92K  /var/share
rpool/dump                       2.06G  49.8G  2.00G  -
rpool/export                      805K  49.7G    32K  /export
rpool/export/home                 773K  49.7G    32K  /export/home
rpool/export/home/ale             741K  49.7G   741K  /export/home/ale
rpool/swap                       1.03G  49.7G  1.00G  -

最后一行指示交换空间为 1GB,是一个 ZFS 卷。可通过执行以下命令验证此信息:

root@solaris11-1:~# ls -l /dev/zvol/rdsk/rpool/swap
lrwxrwxrwx   1 root     root           0 Dec  2 06:31 /dev/zvol/rdsk/rpool/swap -> ../../../..//devices/pseudo/zfs@0:2,raw

因此,更改其大小是可行的,因为 rpool 有些空闲空间,而交换卷属于 rpool 存储池:

root@solaris11-1:~# zfs get volsize rpool/swap
NAME        PROPERTY  VALUE  SOURCE
rpool/swap  volsize   1G     local

root@solaris11-1:~# zfs set volsize=2G rpool/swap
root@solaris11-1:~# zfs get volsize rpool/swap
NAME        PROPERTY  VALUE  SOURCE
rpool/swap  volsize   2G     local

root@solaris11-1:~# swap -l  
swapfile                  dev      swaplo    blocks     free
/dev/zvol/dsk/rpool/swap  285,2         8    097144  2097144
/dev/zvol/dsk/rpool/swap  285,2    097160    097144  2097144

root@solaris11-1:~# swap -s
total: 451556k bytes allocated + 259888k reserved = 711444k used, 3886000k available

root@solaris11-1:~# zfs list -r rpool/swap
NAME         USED  AVAIL  REFER  MOUNTPOINT
rpool/swap  2.06G  48.7G  2.00G  -
root@solaris11-1:~#

不过,并不总是可以更改交换空间的属性,因为它可能很忙。因此,有时需要将另一个卷添加到 rpool 存储池,之后在 /etc/vfstab 末尾插入一行,自动挂载该卷:

root@solaris11-1:~# zfs create -V 2G rpool/newswap
root@solaris11-1:~# swap -a /dev/zvol/dsk/rpool/newswap  
root@solaris11-1:~# swap -l
swapfile                    dev    swaplo   blocks     free
/dev/zvol/dsk/rpool/swap    285,2       8  2097144  2097144
/dev/zvol/dsk/rpool/swap    285,2 2097160  2097144  2097144
/dev/zvol/dsk/rpool/newswap 285,4       8  4194296  4194296

root@solaris11-1:~# swap -s
total: 453668k bytes allocated + 260304k reserved = 713972k used, 5962264k available

root@solaris11-1:~# zfs list -r rpool   
NAME                              USED  AVAIL  REFER  MOUNTPOINT
rpool                            31.6G  46.6G  4.91M  /rpool
rpool/ROOT                       25.4G  46.6G    31K  legacy
rpool/ROOT/solaris               25.4G  46.6G  24.4G  /
rpool/ROOT/solaris-backup-1       138K  46.6G  24.2G  /
rpool/ROOT/solaris-backup-1/var    64K  46.6G   291M  /var
rpool/ROOT/solaris/var            486M  46.6G   234M  /var
rpool/VARSHARE                     92K  46.6G    92K  /var/share
rpool/dump                       2.06G  46.7G  2.00G  -
rpool/export                      805K  46.6G    32K  /export
rpool/export/home                 773K  46.6G    32K  /export/home
rpool/export/home/ale             741K  46.6G   741K  /export/home/ale
rpool/newswap                    2.06G  46.7G  2.00G  -
rpool/swap                       2.06G  46.7G  2.00G  -

root@solaris11-1:~# more /etc/vfstab
#device                    device   mount             FS      fsck    mount     mount
#to mount                  to fsck  point             type    pass    at boot   options
#
/devices                    -       /devices          devf    -       no        -
/proc                       -       /proc             proc    -       no        -
Ctfs                        -       /system/contract  ctfs    -       no        -
Objfs                       -       /system/object    objfs   -       no        -
Sharefs                     -       /etc/dfs/sharetab sharefs -       no        -
Fd                          -       /dev/fd           fd      -       no        -
Swap                        -       /tmp              tmpfs   -       yes       -

/dev/zvol/dsk/rpool/swap    -       -                 swap    -       no        -
/dev/zvol/dsk/rpool/newswap -       -                 swap    -       no        -

显然,反过来就是删除交换空间的过程。例如,执行以下命令,然后删除 /etc/vfstab 文件中的最后一行:

root@solaris11-1:~# swap -d /dev/zvol/dsk/rpool/newswap

另请参见

以下是我撰写的其他一些文章的链接:

以下是有关 Oracle Solaris 11 的一些资源:

关于作者

Alexandre Borges 是一位 Oracle ACE,曾于 2001 至 2010 年任职于 Sun Microsystems,并担任签约讲师,主要负责讲授 Oracle Solaris、Oracle Solaris Cluster、Oracle Solaris 安全性、Java EE、Sun 硬件和 MySQL 课程。目前,他为 Symantec、Oracle 合作伙伴、Hitachi 和 EC-Council 提供课程教学,并且讲授一些关于信息安全的非常专业的课程。此外,他还是 Linux Magazine Brazil 的特约撰稿人和专栏作家。

修订版 1.0,2014 年 4 月 9 日

关注我们:
博客 | Facebook | Twitter | YouTube