linux swap指的是linux交換分割區,是磁碟上的一塊區域,可以是一個分割區,也可以是一個檔案,或者是兩者的組合;swap類似於Windows的虛擬記憶體,就是當記憶體不足時,把一部分硬碟空間虛擬成記憶體使用,從而解決記憶體容量不足的情況。
本教學操作環境:linux5.9.8系統、Dell G3電腦。
linux swap
Linux 的交換分割區(swap),或者叫記憶體置換空間(swap space),是磁碟上的一塊區域,可以是一個分割區,也可以是一個檔案,或者是他們的組合。
SWAP的作用類似Windows系統下的「虛擬記憶體」。當實體記憶體不足時,拿出部分硬碟空間當SWAP分割區(虛擬成記憶體)使用,從而解決記憶體容量不足的情況。
SWAP意思是交換,顧名思義,當某程序向OS請求記憶體發現不足時,OS會把記憶體中暫時不用的資料交換出去,放在SWAP分割區中,這個過程稱為SWAP OUT。當某程序又需要這些資料且OS發現還有空閒實體記憶體時,又會把SWAP分割區中的資料交換回實體記憶體中,這個過程稱為SWAP IN。
當然,swap大小是有上限的,一旦swap使用完,作業系統會觸發OOM-Killer機制,把消耗記憶體最多的程序kill掉以釋放記憶體。
資料庫系統為什麼嫌棄swap?
顯然,swap機制的初衷是為了緩解實體記憶體用盡而選擇直接粗暴OOM程序的尷尬。但坦白講,幾乎所有資料庫對swap都不怎麼待見,無論MySQL、Oracal、MongoDB抑或HBase,為什麼?這主要和下面兩個方面有關:
1. 資料庫系統一般都對響應延遲比較敏感,如果使用swap代替記憶體,資料庫服務效能必然不可接受。對於響應延遲極其敏感的系統來講,延遲太大和服務不可用沒有任何區別,比服務不可用更嚴重的是,swap場景下程序就是不死,這就意味著系統一直不可用……再想想如果不使用swap直接oom,是不是一種更好的選擇,這樣很多高可用系統直接會主從切換掉,使用者基本無感知。
2. 另外對於諸如HBase這類分散式系統來說,其實並不擔心某個節點宕掉,而恰恰擔心某個節點夯住。一個節點宕掉,最多就是小部分請求短暫不可用,重試即可恢復。但是一個節點夯住會將所有分散式請求都夯住,伺服器端執行緒資源被佔用不放,導致整個叢集請求阻塞,甚至叢集被拖垮。
從這兩個角度考慮,所有資料庫都不喜歡swap還是很有道理的!
swap的工作機制
既然資料庫們對swap不待見,那是不是就要使用swapoff命令關閉磁碟快取特性呢?非也,大家可以想想,關閉磁碟快取意味著什麼?實際生產環境沒有一個系統會如此激進,要知道這個世界永遠不是非0即1的,大家都會或多或少選擇走在中間,不過有些偏向0,有些偏向1而已。很顯然,在swap這個問題上,資料庫必然選擇偏向儘量少用。HBase官方檔案的幾點要求實際上就是落實這個方針:儘可能降低swap影響。知己知彼才能百戰不殆,要降低swap影響就必須弄清楚Linux記憶體回收是怎麼工作的,這樣才能不遺漏任何可能的疑點。
先來看看swap是如何觸發的?
簡單來說,Linux會在兩種場景下觸發記憶體回收,一種是在記憶體分配時發現沒有足夠空閒記憶體時會立刻觸發記憶體回收;一種是開啟了一個守護行程(swapd程序)週期性對系統記憶體進行檢查,在可用記憶體降低到特定閾值之後主動觸發記憶體回收。第一種場景沒什麼可說,來重點聊聊第二種場景,如下圖所示:
這裡就要引出我們關注的第一個引數:vm.min_free_kbytes,代表系統所保留空閒記憶體的最低限watermark[min],並且影響watermark[low]和watermark[high]。簡單可以認為:
watermark[min] = min_free_kbytes watermark[low] = watermark[min] * 5 / 4 = min_free_kbytes * 5 / 4 watermark[high] = watermark[min] * 3 / 2 = min_free_kbytes * 3 / 2 watermark[high] - watermark[low] = watermark[low] - watermark[min] = min_free_kbytes / 4
可見,LInux的這幾個水位線與引數min_free_kbytes密不可分。min_free_kbytes對於系統的重要性不言而喻,既不能太大,也不能太小。
min_free_kbytes如果太小,[min,low]之間水位的buffer就會很小,在kswapd回收的過程中一旦上層申請記憶體的速度太快(典型應用:資料庫),就會導致空閒記憶體極易降至watermark[min]以下,此時核心就會進行direct reclaim(直接回收),直接在應用程式的程序上下文中進行回收,再用回收上來的空閒頁滿足記憶體申請,因此實際會阻塞應用程式,帶來一定的響應延遲。當然,min_free_kbytes也不宜太大,太大一方面會導致應用程式程序記憶體減少,浪費系統記憶體資源,另一方面還會導致kswapd程序花費大量時間進行記憶體回收。再看看這個過程,是不是和Java垃圾回收機制中CMS演演算法中老生代回收觸發機制神似,想想引數-XX:CMSInitiatingOccupancyFraction,是不是?官方檔案中要求min_free_kbytes不能小於1G(在大記憶體系統中設定8G),就是不要輕易觸發直接回收。
至此,基本解釋了Linux的記憶體回收觸發機制以及我們關注的第一個引數vm.min_free_kbytes。接下來簡單看看Linux記憶體回收都回收些什麼。Linux記憶體回收物件主要分為兩種:
1. 檔案快取,這個容易理解,為了避免檔案資料每次都要從硬碟讀取,系統會將熱點資料儲存在記憶體中,提高效能。如果僅僅將檔案讀出來,記憶體回收只需要釋放這部分記憶體即可,下次再次讀取該檔案資料直接從硬碟中讀取即可(類似HBase檔案快取)。那如果不僅將檔案讀出來,而且對這些快取的檔案資料進行了修改(髒資料),回收記憶體就需要將這部分資料檔案寫會硬碟再釋放(類似MySQL檔案快取)。
2. 匿名記憶體,這部分記憶體沒有實際載體,不像檔案快取有硬碟檔案這樣一個載體,比如典型的堆、棧資料等。這部分記憶體在回收的時候不能直接釋放或者寫回類似檔案的媒介中,這才搞出來swap這個機制,將這類記憶體換出到硬碟中,需要的時候再載入出來。
具體Linux使用什麼演演算法來確認哪些檔案快取或者匿名記憶體需要被回收掉,這裡並不關心,有興趣可以參考這裡。但是有個問題需要我們思考:既然有兩類記憶體可以被回收,那麼在這兩類記憶體都可以被回收的情況下,Linux到底是如何決定到底是回收哪類記憶體呢?還是兩者都會被回收?這裡就牽出來了我們第二個關心的引數:swappiness,這個值用來定義核心使用swap的積極程度,值越高,核心就會積極地使用swap,值越低,就會降低對swap的使用積極性。該值取值範圍在0~100,預設是60。這個swappiness到底是怎麼實現的呢?具體原理很複雜,簡單來講,swappiness通過控制記憶體回收時,回收的匿名頁更多一些還是回收的檔案快取更多一些來達到這個效果。swappiness等於100,表示匿名記憶體和檔案快取將用同樣的優先順序進行回收,預設60表示檔案快取會優先被回收掉,至於為什麼檔案快取要被優先回收掉,大家不妨想想(回收檔案快取通常情況下不會引起IO操作,對系統效能影響較小)。對於資料庫來講,swap是儘量需要避免的,所以需要將其設定為0。此處需要注意,設定為0並不代表不執行swap哦!
至此,我們從Linux記憶體回收觸發機制、Linux記憶體回收物件一直聊到swap,將引數min_free_kbytes以及swappiness進行了解釋。接下來看看另一個與swap有關係的引數:zone_reclaim_mode,檔案說了設定這個引數為0可以關閉NUMA的zone reclaim,這又是怎麼回事?提起NUMA,資料庫們又都不高興了,很多DBA都曾經被坑慘過。那這裡簡單說明三個小問題:NUMA是什麼?NUMA和swap有什麼關係?zone_reclaim_mode的具體意義?
NUMA(Non-Uniform Memory Access)是相對UMA來說的,兩者都是CPU的設計架構,早期CPU設計為UMA結構,如下圖(圖片來自網路)所示:
為了緩解多核CPU讀取同一塊記憶體所遇到的通道瓶頸問題,晶片工程師又設計了NUMA結構,如下圖(圖片來自網路)所示:
這種架構可以很好解決UMA的問題,即不同CPU有專屬記憶體區,為了實現CPU之間的」記憶體隔離」,還需要軟體層面兩點支援:
1. 記憶體分配需要在請求執行緒當前所處CPU的專屬記憶體區域進行分配。如果分配到其他CPU專屬記憶體區,勢必隔離性會受到一定影響,並且跨越匯流排的記憶體存取效能必然會有一定程度降低。
2. 另外,一旦local記憶體(專屬記憶體)不夠用,優先淘汰local記憶體中的記憶體頁,而不是去檢視遠端記憶體區是否會有空閒記憶體借用。
這樣實現,隔離性確實好了,但問題也來了:NUMA這種特性可能會導致CPU記憶體使用不均衡,部分CPU專屬記憶體不夠使用,頻繁需要回收,進而可能發生大量swap,系統響應延遲會嚴重抖動。而與此同時其他部分CPU專屬記憶體可能都很空閒。這就會產生一種怪現象:使用free命令檢視當前系統還有部分空閒實體記憶體,系統卻不斷髮生swap,導致某些應用效能急劇下降。見葉金榮老師的MySQL案例分析:《找到MySQL伺服器發生SWAP罪魁禍首》。
所以,對於小記憶體應用來講,NUMA所帶來的這種問題並不突出,相反,local記憶體所帶來的效能提升相當可觀。但是對於資料庫這類記憶體大戶來說,NUMA預設策略所帶來的穩定性隱患是不可接受的。因此資料庫們都強烈要求對NUMA的預設策略進行改進,有兩個方面可以進行改進:
1. 將記憶體分配策略由預設的親和模式改為interleave模式,即會將記憶體page打散分配到不同的CPU zone中。通過這種方式解決記憶體可能分佈不均的問題,一定程度上緩解上述案例中的詭異問題。對於MongoDB來說,在啟動的時候就會提示使用interleave記憶體分配策略:
WARNING: You are running on a NUMA machine. We suggest launching mongod like this to avoid performance problems: numactl –interleave=all mongod [other options]
2. 改進記憶體回收策略:此處終於請出今天的第三個主角引數zone_reclaim_mode,這個引數定義了NUMA架構下不同的記憶體回收策略,可以取值0/1/3/4,其中0表示在local記憶體不夠用的情況下可以去其他的記憶體區域分配記憶體;1表示在local記憶體不夠用的情況下本地先回收再分配;3表示本地回收儘可能先回收檔案快取物件;4表示本地回收優先使用swap回收匿名記憶體。可見,HBase推薦設定zone_reclaim_mode=0一定程度上降低了swap發生的概率。
不都是swap的事
至此,我們探討了三個與swap相關的系統引數,並且圍繞Linux系統記憶體分配、swap以及NUMA等知識點對這三個引數進行了深入解讀。除此之外,對於資料庫系統來說,還有兩個非常重要的引數需要特別關注:
1. IO排程策略:這個話題網上有很多解釋,在此並不打算詳述,只給出結果。通常對於sata盤的OLTP資料庫來說,deadline演演算法排程策略是最優的選擇。
2. THP(transparent huge pages)特性關閉。THP特性筆者曾經疑惑過很久,主要疑惑點有兩點,其一是THP和HugePage是不是一回事,其二是HBase為什麼要求關閉THP。經過前前後後多次查閱相關檔案,終於找到一些蛛絲馬跡。這裡分四個小點來解釋THP特性:
(1)什麼是HugePage?
網上對HugePage的解釋有很多,大家可以檢索閱讀。簡單來說,計算機記憶體是通過表對映(記憶體索引表)的方式進行記憶體定址,目前系統記憶體以4KB為一個頁,作為記憶體定址的最小單元。隨著記憶體不斷增大,記憶體索引表的大小將會不斷增大。一臺256G記憶體的機器,如果使用4KB小頁, 僅索引表大小就要4G左右。要知道這個索引表是必須裝在記憶體的,而且是在CPU記憶體,太大就會發生大量miss,記憶體定址效能就會下降。
HugePage就是為了解決這個問題,HugePage使用2MB大小的大頁代替傳統小頁來管理記憶體,這樣記憶體索引表大小就可以控制的很小,進而全部裝在CPU記憶體,防止出現miss。
(2)什麼是THP(Transparent Huge Pages)?
HugePage是一種大頁理論,那具體怎麼使用HugePage特性呢?目前系統提供了兩種使用方式,其一稱為Static Huge Pages,另一種就是Transparent Huge Pages。前者根據名稱就可以知道是一種靜態管理策略,需要使用者自己根據系統記憶體大小手動設定大頁個數,這樣在系統啟動的時候就會生成對應個數的大頁,後續將不再改變。而Transparent Huge Pages是一種動態管理策略,它會在執行期動態分配大頁給應用,並對這些大頁進行管理,對使用者來說完全透明,不需要進行任何設定。另外,目前THP只針對匿名記憶體區域。
(3)HBase(資料庫)為什麼要求關閉THP特性?
THP是一種動態管理策略,會在執行期分配管理大頁,因此會有一定程度的分配延時,這對追求響應延時的資料庫系統來說不可接受。除此之外,THP還有很多其他弊端,可以參考這篇文章《why-tokudb-hates-transparent-hugepages》
(4)THP關閉/開啟對HBase讀寫效能影響有多大?
為了驗證THP開啟關閉對HBase效能的影響到底有多大,本人在測試環境做了一個簡單的測試:測試叢集僅一個RegionServer,測試負載為讀寫比1:1。THP在部分系統中為always以及never兩個選項,在部分系統中多了一個稱為madvise的選項。可以使用命令 echo never/always > /sys/kernel/mm/transparent_hugepage/enabled 來關閉/開啟THP。測試結果如下圖所示:
如上圖,TPH關閉場景下(never)HBase效能最優,比較穩定。而THP開啟的場景(always),效能相比關閉的場景有30%左右的下降,而且曲線抖動很大。可見,HBase線上切記要關閉THP。
相關推薦:《Linux視訊教學》
以上就是linux swap是什麼的詳細內容,更多請關注TW511.COM其它相關文章!