SWAP的罪與罰

SWAP的罪與罰

發表於2012-11-08html

說個案例:一臺Apache服務器,因爲其MaxClients參數設置過大,而且剛好又碰到訪問量激增,結果內存被耗光,從而引起SWAP,進而負載攀升,最終致使宕機。java

 

正所謂:SWAP,性能之大事,死生之地,存亡之道,不可不察也。node

哪些工具能夠監測SWAP

最容易想到的就是free命令了,它指明瞭當前SWAP的使用狀況:mysql

shell> free -m
             total       used       free
Swap:        34175      11374      22801

另外一個經常使用的是sar命令,它能列出系統在各個時間的SWAP使用狀況:linux

shell> sar -r
kbswpfree kbswpused  %swpused  kbswpcad
 23345644  11650572     33.29   4656908
 23346452  11649764     33.29   4656216
 23346556  11649660     33.29   4650308
 23346932  11649284     33.29   4649888
 23346992  11649224     33.29   4648848

不過free命令和sar命令顯示的都不是實時數據,若是須要,可使用vmstat命令:git

shell> vmstat 1
-----------memory------------- ---swap--
  swpd   free   buff   cache     si   so
11647532 123664 305064 7193168    0    0
11647532 123672 305064 7193172    0    0
11647532 125728 305064 7193468    0    0
11647532 125376 305064 7193476    0    0
11647532 124508 305068 7193624    0    0

每秒刷新一次結果,在SWAP一欄裏列出了相關數據,至於si和so的解釋,大體以下:github

  • si: Amount of memory swapped in from disk (/s).
  • so: Amount of memory swapped to disk (/s).

若是它們一直是零固然最好不過了,偶爾不爲零也沒啥,糟糕的是一直不爲零。sql

前面介紹的方法,看到的都是SWAP的總體狀況,但是若是我想查看究竟是哪些進程使用了SWAP,應該如何操做呢?這個問題有點棘手,咱們來研究一下:shell

好消息是top命令能提供這個信息,不過缺省並無顯示,咱們須要激活一下:數據庫

  1. 打開top;
  2. 按「f」進入選擇字段的界面;
  3. 按「p」選擇「SWAP」字段;
  4. 按回車確認。

壞消息是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 = 1" >> /etc/sysctl.conf
shell> sysctl -p

這樣作的確能夠下降執行SWAP的機率,但並不意味着永遠不會執行SWAP。據網友報道某些狀況下,直接改成0有可能出現靈異問題,因此建議改成1。

NUMA的詛咒

NUMAMySQL社區有不少討論,這裏很少說了,直擊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內存的,若是須要知道,咱們能夠利用drop_caches參數先釋放它:

shell> sysctl vm.drop_caches=1

注:這步操做可能會引發系統負載的震盪。

另:如何肯定一個進程的節點及內存分配狀況?網絡上有現成的腳本

若是要規避NUMA對SWAP的影響,最簡單的方法就是在啓動進程的時候禁用它:

shell> numactl --interleave=all ...

此外,內核參數zone_reclaim_mode一般也很重要,當某個節點可用內存不足時,若是爲0的話,那麼系統會傾向於從遠程節點分配內存;若是爲1的話,那麼系統會傾向於從本地節點回收Cache內存。多數時候,Cache對性能很重要,因此0是一個更好的選擇。

shell> echo "vm.zone_reclaim_mode = 0" >> /etc/sysctl.conf
shell> sysctl -p

另:網絡上有一些關於MySQL和SWAP的討論,對於理解SWAP有必定意義,推薦:

補:Memcached在啓動的時候若是帶上了k選項,就能避免使用SWAP,但要慎用。

早些年,YouTube曾經被SWAP問題困擾過,他們當時的解決方法很極端:刪除SWAP!不得不說這真是藝高人膽大,惋惜對芸芸衆生的咱們而言,這實在是太危險了,由於如此一來,一旦內存耗盡,因爲沒有SWAP的緩衝,系統會當即開始OOM,結果可能會讓問題變得更加複雜,因此你們仍是安分守己作個老實人吧。

 

  1. Jacky在2012-11-08 16:33:29說道:

    Google內部絕大部分的服務都是直接取消swap的,由於相對於swap致使系統變慢而言,不如直接OOM死掉反而是很方便的方法——反正系統自己具備魯棒性,原本就設計有容錯機制的。

    回覆 ↓

  2. 聰在2012-11-08 19:53:40說道:

    個人程序可能也遇到了這個問題。。線上導出大文件後,cache被吃掉不少內存,可能致使java那邊的一些內存就被擠到swap了(但我在sar的歷史日誌裏,沒有看到swap明顯升高,因此還不肯定。。)

    另外,若是用mlockall事先鎖住一起內存給java使用是否可行呢?盼賜教。

    回覆 ↓

    • 老王在2012-11-08 21:22:51說道:

      第一個問題信息不足沒法回答;第二個問題答案是確定的,事實上,memcached就是用mlockall方法來禁止swap的(k選項)。

    • 聰在2012-11-08 21:35:29說道:

      多謝!

      我想進一步問一下。咱們線上用的是一臺5g的虛擬機,ulimit -l結果是32。請問這個能不能設置成unlimited呢?
      比較擔憂會對同宿主的其餘虛擬機形成影響。

    • 老王在2012-11-08 22:22:36說道:

      理論上是能夠設置max locked memory到unlimited的,不過這樣雖然能夠避免SWAP,可是還須要注意OOM的影響,你能夠結合本身的程序模擬一些極端狀況看看。只有測試才能給出正確的答案。

    • 聰在2012-11-09 09:40:30說道:

      好的。

  3. Pingback引用通告: 【轉載】SWAP的罪與罰 | 一意孤星的世界

  4. 王子2012-11-10 21:16:10說道:

    這個東西玄乎的好像根本不可控制同樣,這種資源問題原本就應該讓系統來支配纔對!本身還要去管理,好麻煩啊

    回覆 ↓

  5. 軒脈刃2012-12-07 09:52:32說道:

    參考這篇文章:說的是爲了追求程序速度,手動綁定NUMA,看來速度和內存是兩個須要平衡的東西。。。

    回覆 ↓

  6. link-tec2012-12-25 21:04:02說道:

    au,very nice..

    回覆 ↓

  7. Terry2012-12-31 09:40:50說道:

    其實 dstat 也是很不錯的工具;-) 從系統管理的角度來說(對 mysql 理解不夠深刻),只要 vmstat 輸出中 si/so 不頻繁即說明物理內存還夠用。free 輸出中 free + cached + buffer = + buffers/cache 的值,內核參數 drop_caches 只能釋放 page cache 一般內核會管理,不用人肉 drop ...

    經驗告訴我在最好別設置 swappiness 爲 0 不然系統可能出現詭異的性能問題,由於存在沒法判斷的突發內存消耗,致使 page out 系統性能急速惡化。

    回覆 ↓

  8. ACb0y在2014-12-08 19:21:58說道:

    很好的分享。

    回覆 ↓

  9. YQ在2015-01-16 10:25:45說道:

    「另外一個經常使用的是sar命令,它能列出系統在各個時間的SWAP使用狀況:shell> sar -r」
    這裏應該是 sar -S 吧。

    回覆 ↓

  10. C永東在2015-09-22 16:10:03說道:

    今年新到一臺HP服務器 安裝了windows 08R2 數據庫 MS SQL 08R2 雙cpu 發現滿負載的時候,任務管理器顯示49% 其中的10核20線程所有到頂了;可是另一個CPU動都不動一下~ 這個是否是得取消掉默認的numa,改成普通的smp

相關文章
相關標籤/搜索