發表於2012-11-08html
說個案例:一臺Apache服務器,因爲其MaxClients參數設置過大,而且剛好又碰到訪問量激增,結果內存被耗光,從而引起SWAP,進而負載攀升,最終致使宕機。java
正所謂:SWAP,性能之大事,死生之地,存亡之道,不可不察也。node
最容易想到的就是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
若是它們一直是零固然最好不過了,偶爾不爲零也沒啥,糟糕的是一直不爲零。sql
前面介紹的方法,看到的都是SWAP的總體狀況,但是若是我想查看究竟是哪些進程使用了SWAP,應該如何操做呢?這個問題有點棘手,咱們來研究一下:shell
好消息是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 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的詛咒
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內存的,若是須要知道,咱們能夠利用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,結果可能會讓問題變得更加複雜,因此你們仍是安分守己作個老實人吧。
Jacky在2012-11-08 16:33:29說道:
Google內部絕大部分的服務都是直接取消swap的,由於相對於swap致使系統變慢而言,不如直接OOM死掉反而是很方便的方法——反正系統自己具備魯棒性,原本就設計有容錯機制的。
聰在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說道:
好的。
Pingback引用通告: 【轉載】SWAP的罪與罰 | 一意孤星的世界
這個東西玄乎的好像根本不可控制同樣,這種資源問題原本就應該讓系統來支配纔對!本身還要去管理,好麻煩啊
參考這篇文章:說的是爲了追求程序速度,手動綁定NUMA,看來速度和內存是兩個須要平衡的東西。。。
link-tec在2012-12-25 21:04:02說道:
au,very nice..
其實 dstat
也是很不錯的工具;-) 從系統管理的角度來說(對 mysql 理解不夠深刻),只要 vmstat 輸出中 si/so 不頻繁即說明物理內存還夠用。free 輸出中 free + cached + buffer = + buffers/cache 的值,內核參數 drop_caches 只能釋放 page cache 一般內核會管理,不用人肉 drop ...
經驗告訴我在最好別設置
swappiness
爲 0 不然系統可能出現詭異的性能問題,由於存在沒法判斷的突發內存消耗,致使 page out 系統性能急速惡化。
ACb0y在2014-12-08 19:21:58說道:
很好的分享。
YQ在2015-01-16 10:25:45說道:
「另外一個經常使用的是sar命令,它能列出系統在各個時間的SWAP使用狀況:shell> sar -r」
這裏應該是 sar -S 吧。
C永東在2015-09-22 16:10:03說道:
今年新到一臺HP服務器 安裝了windows 08R2 數據庫 MS SQL 08R2 雙cpu 發現滿負載的時候,任務管理器顯示49% 其中的10核20線程所有到頂了;可是另一個CPU動都不動一下~ 這個是否是得取消掉默認的numa,改成普通的smp