SWAP的罪与罚
说个案例:一台Apache服务器,由于其MaxClients参数设置过大,并且恰好又碰到访问量激增,结果内存被耗光,从而引发SWAP,进而负载攀升,最终导致宕机。
正所谓:SWAP,性能之大事,死生之地,存亡之道,不可不察也。
哪些工具可以监测SWAP
最容易想到的就是free命令了,它指明了当前SWAP的使用情况:
shell> free -m total used free shared buffers cached Mem: 32178 32075 103 0 298 7032 -/+ buffers/cache: 24744 7433 Swap: 34175 11374 22801
另一个常用的是sar命令,它能列出系统在各个时间的SWAP使用情况:
shell> sar -r 01:00:01 AM kbmemfree kbmemused %memused kbbuffers kbcached kbswpfree kbswpused %swpused kbswpcad 01:00:01 AM 164112 32786496 99.50 274340 7347520 23345644 11650572 33.29 4656908 01:10:01 AM 106940 32843668 99.68 278612 7409376 23346452 11649764 33.29 4656216 01:20:01 AM 93244 32857364 99.72 317368 7369564 23346556 11649660 33.29 4650308 01:30:01 AM 126316 32824292 99.62 320896 7401228 23346932 11649284 33.29 4649888 01:40:01 AM 126824 32823784 99.62 323692 7365428 23346992 11649224 33.29 4648848
不过free命令和sar命令显示的都不是实时数据,如果需要,可以使用vmstat命令:
shell> vmstat 1 procs -----------memory------------- ---swap-- -----io---- --system-- -----cpu------ r b swpd free buff cache si so bi bo in cs us sy id wa st 2 0 11647532 123664 305064 7193168 0 0 6 155 0 0 8 2 90 0 0 0 0 11647532 123672 305064 7193172 0 0 12 0 6626 14699 6 2 92 0 0 0 0 11647532 125728 305064 7193468 0 0 12 0 6717 13706 5 2 93 0 0 2 0 11647532 125376 305064 7193476 0 0 24 0 6830 15961 7 2 91 0 0 1 0 11647532 124508 305068 7193624 0 0 0 1164 6645 13363 6 2 92 0 0
每秒刷新一次结果,在SWAP一栏里列出了相关数据,至于si和so的解释,大致如下:
si: Amount of memory swapped in from disk (/s).
so: Amount of memory swapped to disk (/s).
打开top;
按「f」进入选择字段的界面;
按「p」选择「SWAP」字段;
按回车确认。
如果它们一直是零当然最好不过了,偶尔不为零也没啥,糟糕的是一直不为零。
前面介绍的方法,看到的都是SWAP的整体情况,可是如果我想查看到底是哪些进程使用了SWAP,应该如何操作呢?这个问题有点棘手,我们来研究一下:
好消息是top命令能提供这个信息,不过缺省并没有显示,我们需要激活一下:
坏消息是top命令提供的SWAP信息只是一个理论值,或者更直白一点儿来说它根本就是不可信的(在top里SWAP的计算公式是:SWAP=VIRT-RES)。
BTW:相比之下,top里的「nFLT」字段更有价值,它表示PageFault的次数。
那到底我们能不能获取到进程的SWAP情况呢?别着急,看代码:
#!/bin/bash cd /proc for pid in [0-9]*; do command=$(cat /proc/$pid/cmdline) swap=$( awk \' BEGIN { total = 0 } /Swap/ { total += $2 } END { print total } \' /proc/$pid/smaps ) if (( $swap > 0 )); then if [[ "${head}" != "yes" ]]; then echo -e "PID\\tSWAP\\tCOMMAND" head="yes" fi echo -e "${pid}\\t${swap}\\t${command}" fi done
说明:请使用root权限来运行此脚本。
哪些因素可能影响SWAP
内存不足无疑会SWAP,但有些时候,即便看上去内存很充裕,还可能会SWAP,这种现象被称为SWAP Insanity,罪魁祸首主要有以下几点:
Swappiness的迷失
实际上,当可用内存不足时,系统有两个选择:一个是通过SWAP来释放内存,另一个是删除Cache中的Page来释放内存。一个很常见的例子是:当拷贝大文件的时候,时常会发生SWAP现象。这是因为拷贝文件的时候,系统会把文件内容在Cache中按Page来缓存,此时一旦可用内存不足,系统便会倾向于通过SWAP来释放内存。
内核中的swappiness参数可以用来控制这种行为,缺省情况下,swappiness的值是60:
shell> sysctl -a | grep swappiness vm.swappiness = 60
它的含义是:如果系统需要内存,有百分之六十的概率执行SWAP。知道了这一点,我们很自然的会想到用下面的方法来降低执行SWAP的概率:
shell> echo "vm.swappiness = 0" >> /etc/sysctl.conf shell> sysctl -p
这样做的确可以降低执行SWAP的概率,但并不意味着永远不会执行SWAP。
NUMA的诅咒
NUMA在MySQL社区有很多讨论,这里不多说了,直击NUMA和SWAP的恩怨纠葛。
大概了解一下NUMA最核心的numactl命令:
shell> numactl --hardware available: 2 nodes (0-1) node 0 size: 16131 MB node 0 free: 100 MB node 1 size: 16160 MB node 1 free: 10 MB node distances: node 0 1 0: 10 20 1: 20 10
可以看到系统有两个节点(其实就是两个物理CPU),它们各自分了16G内存,其中零号节点还剩100M内存,一号节点还剩10M内存。设想启动了一个需要11M内存的进程,系统把它分给了一号节点来执行,此时虽然系统总体的可用内存大于该进程需要的内存,但因为一号节点本身剩余的可用内存不足,所以仍然可能会触发SWAP行为。
需要说明的一点事,numactl命令中看到的各节点剩余内存中时不包括Cache内存的,实际上Cache也是可用的,如果需要知道,我们可以利用drop_caches参数先释放它:
shell> sysctl vm.drop_caches=1
注:这步操作可能会引起系统负载的震荡。
另:如何确定一个进程的节点及内存分配情况?网络上有现成的脚本。
如果要规避NUMA对SWAP的影响,最简单的方法就是在启动进程的时候禁用它:
shell> echo 0 > /proc/sys/vm/zone_reclaim_mode shell> numactl --interleave=all ...
另:网络上有一些关于MySQL和SWAP的讨论,对于理解SWAP有一定意义,推荐:
补:Memcached在启动的时候如果带上了k选项,就能避免使用SWAP,但要慎用。
…
早些年,YouTube曾经被SWAP问题困扰过,他们当时的解决方法很极端:删除SWAP!不得不说这真是艺高人胆大,可惜对芸芸众生的我们而言,这实在是太危险了,因为如此一来,一旦内存耗尽,由于没有SWAP的缓冲,系统会立即开始OOM,结果可能会让问题变得更加复杂,所以大家还是安分守己做个老实人吧。
建议继续学习:
- Linux服务器性能评估 (阅读:8151)
- Linux 64位, MySQL, Swap & Memory 优化 (阅读:4459)
- 关于Linux系统安装中Swap分区的解释 (阅读:4043)
- linux磁盘管理学习笔记补充:连接ln、虚拟内存 (阅读:2980)
- linux调整swap大小 (阅读:2510)
- Linux Swap -- 创建普通文件作为swap (阅读:2437)
- 一个监测服务器swap并重启php的脚本 (阅读:2289)
- 服务器中swap 的划分 (阅读:2242)
- 使用vi命令出现Swap file "..." already exists!警告 (阅读:1509)
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:老王 来源: 火丁笔记
- 标签: SWAP
- 发布时间:2012-11-11 23:40:46
- [68] Go Reflect 性能
- [68] 如何拿下简短的域名
- [67] Oracle MTS模式下 进程地址与会话信
- [62] IOS安全–浅谈关于IOS加固的几种方法
- [61] 图书馆的世界纪录
- [60] 【社会化设计】自我(self)部分――欢迎区
- [58] android 开发入门
- [56] 视觉调整-设计师 vs. 逻辑
- [49] 给自己的字体课(一)——英文字体基础
- [48] 读书笔记-壹百度:百度十年千倍的29条法则