哈嘍大家好,我是鹹魚。 今天收到了一個告警,說有台伺服器上的 swap 過高,已經用了 50% 以上了。 登錄機器查看一下記憶體以及 swap 的使用情況。 [root@localhost ~]# free -h total used free shared buff/cache available ...
哈嘍大家好,我是鹹魚。
今天收到了一個告警,說有台伺服器上的 swap 過高,已經用了 50% 以上了。
登錄機器查看一下記憶體以及 swap 的使用情況。
[root@localhost ~]# free -h
total used free shared buff/cache available
Mem: 62G 27G 2.9G 568M 32G 33G
swap: 16G 8.3G 8.1G
可以看到還有 2.9G 的空閑物理記憶體,但是系統已經開始使用 swap 了,初步判斷是機器上面的程式記憶體需求比較大,但物理記憶體不夠用所以開始使用 swap 來存儲部分數據。
什麼是 swap
swap 顧名思義指的是 Linux 上的交換分區,有點像 Windows 的虛擬記憶體,說白了就是把一塊磁碟空間或者一個本地文件當成記憶體來使用。
在早期記憶體價格昂貴的時代,swap 的出現解決了物理記憶體不足導致無法運行程式的問題。
swap 包含換出和換入兩個過程:
- 換出:把進程暫時不用的記憶體數據存儲到磁碟中,並釋放這些數據占用的記憶體。
- 換入:進程再次訪問這些記憶體數據時,把它們從磁碟讀到記憶體來。
那現在隨著記憶體越來越便宜,伺服器上面的記憶體也越來越大,swap 是不是就沒啥作用了呢?
不是的,對於程式來說,記憶體再大也有不夠用的時候。比如說記憶體不足的時候,有些程式不希望被 OOM 殺死,而是希望等待一段時間讓人工來處理,或者等系統自動釋放其他進程的記憶體之後再分配給它。
又比如我們常見的筆記本電腦的休眠和快速開機的功能確實是基於 swap 的。在休眠時,操作系統會將當前記憶體的狀態保存到交換空間或者稱為休眠文件中,然後關閉電腦。當再次開機時,系統可以直接從休眠文件中恢復記憶體狀態,而不需要重新載入應用程式和初始化系統,從而實現了快速開機的功能。
在 Linux 中,/proc/sys/vm/swappiness
用來調整使用 swap 的積極程度。swappiness 的範圍是 0-100,數值越大,越積極使用 swap。一般來講預設值是 60 。
需要註意的是:這個範圍是 swap 積極程度的權重,即使我們設置成 0,在某些情況下(例如進程可用記憶體耗盡了)還是會使用 swap 的。
排查過程
首先我們來看下 swap 的積極程度。
[root@localhost ~]# cat /proc/sys/vm/swappiness
60
swappiness 顯示的是預設值 60,這是一個相對中和的配置,所以系統會根據實際情況來選擇是回收可用緩存以增加可用記憶體空間,還是使用交換空間來增加可用記憶體空間。
接下來我們要找出是哪些進程使用到了 swap。在 Linux 中,可以用 proc 文件系統來查看進程 swap 換出的虛擬記憶體大小,它保存在 /proc/pid/status
的 Vmswap 欄位中。
但是一臺伺服器中有這麼多進程,一個一個找太麻煩了,所以我們可以使用下麵的命令來找出當前系統中 swap 占用最大的幾個進程,併列出它們的進程號、進程名和 swap 大小。
[root@localhost ~]# for file in /proc/*/status ; do awk '/Vmswap|Name|^Pid/{printf $2 " " $3}END{ print ""}' $file; done | sort -k 3 -n -r | head
java 153707 3245376 kB
java 153544 1757916 kB
java 172612 732100 kB
java 323072 339756 kB
java 172807 161988 kB
for file in /proc/*/status ; do ... done
:這是一個 for 迴圈,它遍歷了/proc
目錄下的所有子目錄,每個子目錄都包含一個名為status
的文件,其中包含了該進程的一些狀態信息。awk '/VmSwap|Name|^Pid/{printf $2 " " $3}END{ print ""}' $file
:對於每個/proc/*/status
文件,awk 命令用於匹配VmSwap
、Name
或者Pid
這幾個關鍵字,並輸出它們的值。這些關鍵字分別表示交換空間、進程名和進程號。sort -k 3 -n -r
:對輸出的結果進行排序。-k 3
表示按第三列進行排序,即按照交換空間大小排序;-n
表示按照數字順序排序;-r
表示逆序排序,即從大到小排序。head -5
:輸出排序後的前5行。
從輸出的結果可以看到,使用 swap 比較多的是 java 進程。
如何解決
在定位到是哪些進程使用 swap 比較高之後,我們找到對應的開發同事進行討論,最後決定把 swap 關掉。通常來講,降低 swap 的使用,可以提高系統的整體性能。
一方面是因為頻繁地進行 swap 操作,會導致大量的磁碟讀寫操作,降低系統的響應速度和整體性能。
另一方面是因為頻繁地將數據從記憶體交換到 swap 空間,併在需要時再次交換回來時,會增加 CPU 和記憶體的負擔。
如何關閉 swap ?
首先使用 swapoff
命令關閉當前正在使用的交換空間。
[root@localhost ~]# swapoff -a
然後我們看下 swap 空間是否已經關閉,如果輸出為空則表示 swap 成功關閉。
[root@localhost ~]# cat /proc/swaps
需要註意的是,前面的 swap 關閉操作只是臨時關閉,如果機器重啟是會重新開啟 swap 的。
所以為了下一次重啟機器後 swap 還是關閉狀態我們還要編輯 /etc/fstab
文件,將其中關於 swap 的配置註釋掉或者刪除掉。
# 找到以 swap 標識的行,然後註釋
[root@localhost ~]# vim /etc/fstab
# /dev/mapper/centos-swap swap swap
這樣如果機器後面要是重啟了,swap 依舊是關閉狀態。