為什么系統(tǒng)Swap變高了

swap用來(lái)做什么

緩存和緩沖區(qū)屬于可回收內(nèi)存,它們?cè)趦?nèi)存管理中,通常被叫做文件頁(yè)(File- backed page)大部分文件頁(yè)都可以直接回收,以后需要時(shí),再?gòu)拇疟P重新讀取就可以了,那些被應(yīng)用程序修改過(guò),并且暫時(shí)沒(méi)有寫入磁盤的數(shù)據(jù)(臟頁(yè))就得先寫入磁盤,然后才能進(jìn)行內(nèi)存釋放

除了文件頁(yè)外,應(yīng)用程序動(dòng)態(tài)分配的堆內(nèi)存叫做匿名頁(yè)(Anonymous Page)如堆,棧,數(shù)據(jù)段等,不是以文件形式存在,因此無(wú)法和磁盤文件交換,是通過(guò)swap機(jī)制把不常訪問(wèn)匿名頁(yè)占用的內(nèi)存寫入到磁盤中,然后釋放這些內(nèi)存,再次方式這些內(nèi)存時(shí),重新沖磁盤寫入內(nèi)存就可以了

匿名頁(yè) 和 文件頁(yè) 的回收都是基于LRU算法,優(yōu)先回收不常訪問(wèn)的內(nèi)存,所以LRU維護(hù)了active和inactive兩個(gè)雙向鏈表

  • active:記錄活躍內(nèi)存頁(yè)
  • inactive:記錄不活躍內(nèi)存頁(yè)

活躍和非活躍的 匿名頁(yè) 和 文件頁(yè) 大小查看

cat /proc/meminfo | grep -i active | sort
Active:           274616 kB
Active(anon):      38224 kB
Active(file):     236392 kB
Inactive:         320624 kB
Inactive(anon):      136 kB
Inactive(file):   320488 kB

swap 原理

Swap就是把一塊磁盤空間或者本地文件想做內(nèi)存來(lái)使用,它包括換出和換入兩個(gè)過(guò)程

  • 換出:就是把進(jìn)程暫時(shí)不用的內(nèi)存數(shù)據(jù)存儲(chǔ)到磁盤中,并且釋放這些數(shù)據(jù)占用的內(nèi)存
  • 換入:進(jìn)程再次訪問(wèn)這些內(nèi)存的時(shí)候,把它們從磁盤讀取到內(nèi)存中

使用場(chǎng)景

Swap其實(shí)就是把系統(tǒng)的可用內(nèi)存變大了,即使服務(wù)器內(nèi)存不足,頁(yè)可用運(yùn)行大內(nèi)存的應(yīng)用程序

  • 內(nèi)存不足時(shí),有些程序并不想被OOM殺死,而是希望能緩一段時(shí)間,等待人工介入或者等系統(tǒng)自動(dòng)釋放其他進(jìn)程的內(nèi)容,再分配給它就會(huì)用到swap

  • swap也是為了回收匿名頁(yè)占用的內(nèi)存

  • 直接內(nèi)存回收:當(dāng)有大塊內(nèi)存分配請(qǐng)求,但是內(nèi)存不足,這時(shí)候系統(tǒng)就會(huì)回收一部分內(nèi)存(比如緩存)盡可能的滿足新內(nèi)存的請(qǐng)求,這個(gè)過(guò)程叫做 直接內(nèi)存回收

  • 定時(shí)內(nèi)存回收:內(nèi)核kswapd0線程用來(lái)定時(shí)回收內(nèi)存,為了衡量?jī)?nèi)存的使用情況,kswapd0定義了三個(gè)內(nèi)存閾值是 頁(yè)最小閾值(pages_min),頁(yè)低閾值(pages_low)和頁(yè)高閾值(pages_high),剩余內(nèi)存則使用pages_free表示

image.png
  • 剩余內(nèi)存 < 頁(yè)最小閾值:說(shuō)明內(nèi)存可用內(nèi)存都耗盡了,只有內(nèi)核才可以分配內(nèi)存
  • 剩余內(nèi)存落在頁(yè)最小閾值頁(yè)低閾值中間:說(shuō)明內(nèi)存使用比較大,剩余內(nèi)存不多了,kswapd0回執(zhí)行內(nèi)存回收,知道剩余內(nèi)存大于高閾值為止
  • 剩余內(nèi)存落在頁(yè)低閾值頁(yè)高閾值中間:說(shuō)明內(nèi)存有一定壓力,但是還可以滿足新內(nèi)存請(qǐng)求。
  • 剩余內(nèi)存 > 頁(yè)高閾值:說(shuō)明剩余內(nèi)存比較對(duì),沒(méi)有內(nèi)存壓力

頁(yè)低賦值可以通過(guò)內(nèi)核選項(xiàng)vm.min_free_kbytes 間接設(shè)置 /proc/sys/vm/min_free_kbytes,min_free_kbytes設(shè)置了頁(yè)最小閾值,其他兩個(gè)閾值根據(jù)頁(yè)最小閾值計(jì)算生成的

pages_low = pages_min*5/4
pages_high = pages_min*3/2

NUMA與Swap

有時(shí)候系統(tǒng)內(nèi)存剩余還很多,但是Swap還是升高了,是因?yàn)樘幚砥鱊UMA架構(gòu)導(dǎo)致的

在NUMA框架下,多個(gè)處理器被劃分到不同Node上,且每個(gè)Node 都擁有自己的本地內(nèi)存空間,并且進(jìn)一步又分為內(nèi)內(nèi)參域(zone),不如 直接內(nèi)存訪問(wèn)區(qū)(DMA),普通內(nèi)存區(qū)(NORMAL),偽內(nèi)存區(qū)(MOVABLE)等

因?yàn)镹UMA框架下每個(gè)Node都有自己的本地內(nèi)存空間,所以分析內(nèi)存使用需要根據(jù)每個(gè)Node單獨(dú)分析, 可以通過(guò)numactl 查看每個(gè)Node內(nèi)存使用情況

[root@master1 ~]# numactl --hardware
available: 1 nodes (0)
node 0 cpus: 0 1 2 3
node 0 size: 8191 MB
node 0 free: 1793 MB
node distances:
node   0
  0:  10

根據(jù)這個(gè)輸出,我們系統(tǒng)中只有一個(gè)Node,就是Node0,編號(hào)為0 1 2 3的CPU都位于Node0上。另外Node0的內(nèi)存大小為 8191 MB,剩余1793 MB

前面提到的頁(yè)最小,頁(yè)低,頁(yè)高的三個(gè)閾值都可以在內(nèi)存域/proc/zoneinfo來(lái)查看

[root@master1 ~]# cat /proc/zoneinfo | grep -i -A 15 "Node 0"
Node 0, zone      DMA
  pages free     3975
        min      30
        low      37
        high     45
        scanned  0
        spanned  4095
        present  3998
        managed  3977
    nr_free_pages 3975
    nr_alloc_batch 8
    nr_inactive_anon 0
    nr_active_anon 0
    nr_inactive_file 0
    nr_active_file 0
    nr_unevictable 0
--
Node 0, zone    DMA32
  pages free     159434
        min      5530
        low      6912
        high     8295
        scanned  0
        spanned  1044480
        present  782327
        managed  721081
    nr_free_pages 159434
    nr_alloc_batch 1343
    nr_inactive_anon 14605
    nr_active_anon 95179
    nr_inactive_file 193717
    nr_active_file 206850
    nr_unevictable 0
--
Node 0, zone   Normal
  pages free     295068
        min      9798
        low      12247
        high     14697
        scanned  0
        spanned  1310720
        present  1310720
        managed  1277513
    nr_free_pages 295068
    nr_alloc_batch 127
    nr_inactive_anon 16505
    nr_active_anon 141332
    nr_inactive_file 335925
    nr_active_file 383442
    nr_unevictable 0

上面輸出包含了三個(gè)內(nèi)存域的指標(biāo),min,low,high 就是上面提到的三個(gè)內(nèi)存閾值,而free是剩余內(nèi)存頁(yè)數(shù)它跟后面的nr_free_pages相同 注意: 這里單位是頁(yè),每一頁(yè)是4kb,比如計(jì)算頁(yè)最小閾值需要把 三個(gè)zone的min相加 * 4kb(9798 + 5530 + 30)* 4

根據(jù)輸入內(nèi)容發(fā)現(xiàn)pages free剩余內(nèi)存遠(yuǎn)高于high,所以此時(shí)kswapd0不會(huì)回收內(nèi)存,當(dāng)某個(gè)Node內(nèi)存不足時(shí),系統(tǒng)可以從其他Node尋找空閑內(nèi)容,頁(yè)可以從本地內(nèi)存中回收內(nèi)存,需要選哪個(gè)模式,可以通過(guò)/proc/sys/vm/zone_reclaim_mode來(lái)調(diào)整

  • 默認(rèn)為0,也就是剛剛提到的模式,表示既可以從其他Node尋找空閑內(nèi),頁(yè)可以從本地回收內(nèi)存,這時(shí)候就會(huì)導(dǎo)致回收文件頁(yè)和匿名頁(yè)匿名頁(yè)的回收所以會(huì)觸發(fā)swap
  • 1,2,4,表示只回收本地內(nèi)存,2表示可以回收寫臟數(shù)據(jù)回收內(nèi)存,4表示可以用Swap方式回收內(nèi)存

swappiness

使用swap的積極程度可以通過(guò)內(nèi)核參數(shù) vm.swappiness 間接配置 /proc/sys/vm/swappiness 選項(xiàng),配置范圍0-100,數(shù)字越大,越積極使用Swap,也就是更傾向于回收匿名頁(yè),數(shù)值越小,越消極使用Swap

即使你設(shè)置為0,當(dāng)剩余內(nèi)存文件頁(yè)小于高閾值時(shí),還是會(huì)發(fā)生Swap

# 按VmSwap使用量對(duì)進(jìn)程排序,輸出進(jìn)程名稱、進(jìn)程ID以及SWAP用量
$ for file in /proc/*/status ; do awk '/VmSwap|Name|^Pid/{printf $2 " " $3}END{ print ""}' $file; done | sort -k 3 -n -r | head
dockerd 2226 10728 kB
docker-containe 2251 8516 kB
snapd 936 4020 kB
networkd-dispat 911 836 kB
polkitd 1004 44 kB

總結(jié)

Linux通過(guò)直接內(nèi)存回收和定時(shí)內(nèi)存掃描回收方式來(lái)釋放文件頁(yè)和匿名頁(yè)

  • 文件頁(yè)的回收:就是直接回收緩存,或者把臟數(shù)據(jù)寫回磁盤后釋放
  • 匿名也的回收:需要通過(guò)Swap換出到磁盤中,下次訪問(wèn)時(shí),在從磁盤換入到內(nèi)存中

定時(shí)內(nèi)存掃描回收方式的閾值可以通過(guò)內(nèi)核選項(xiàng)vm.min_free_kbytes來(lái)設(shè)置

只要涉及到回收匿名頁(yè)就會(huì)涉及觸發(fā)Swap

假如沒(méi)有開啟swap的話,進(jìn)程的匿名頁(yè)就無(wú)法釋放,需要在進(jìn)程的重啟或者殺掉釋放

swap使用積極程度可以通過(guò)內(nèi)核參數(shù)vm.swappiness 設(shè)置

在處理器NUMA框架下,每個(gè)Node都有自己的內(nèi)存域,某個(gè)Node自己內(nèi)存域下剩余內(nèi)存不多情況下,導(dǎo)致內(nèi)存回收也就有可能觸發(fā)Swap

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容