首頁 >運維 >linux運維 >總結Linux磁碟快取相關知識

總結Linux磁碟快取相關知識

藏色散人
藏色散人轉載
2021-10-29 16:16:431939瀏覽

以下由linux系統教學欄位介紹給大家總結關於Linux磁碟快取的相關知識,希望對需要的朋友有幫助!

前言

最近遇到了一起跟磁碟相關的線上故障,藉此總結一下之前不太了解的Linux磁碟快取相關的知識。

總的來說磁碟快取出現的原因大概有兩個:第一是存取磁碟的速度遠慢於存取記憶體的速度,透過在記憶體中快取磁碟內容可以提高存取速度;第二是根據程式的局部性原理,資料一旦被訪問過,就很有可能在短時間內再次被訪問,所以在記憶體中快取磁碟內容可以提高程式運行速度。

局部性原理

程式局部性原理:程式在執行時呈現出局部性規律,即在一段時間內,整個程式的執行僅限於程式中的某一部分。相應地,執行所存取的儲存空間也局限於某個記憶體區域,具體來說,局部性通常有兩種形式:時間局部性和空間局部性。

時間局部性:被引用過一次的記憶體位置在未來會被多次引用。

空間局部性:如果一個記憶體的位置被引用,那麼將來他附近的位置也會被引用。

頁快取

Linux系統中為了減少對磁碟的IO操作,會將開啟的磁碟內容進行緩存,而快取的地方則是物理內存,進而將對磁碟的存取轉換成對記憶體的訪問,有效提高程式的速度。 Linux的快取方式是利用實體記憶體快取磁碟上的內容,稱為頁面快取(page cache)。

頁快取是由記憶體中的實體頁面組成的,其內容對應磁碟上的實體區塊。頁面快取的大小會根據系統的記憶體空閒大小進行動態調整,它可以透過佔用記憶體以擴張大小,也可以自我收縮以緩解記憶體使用壓力。

在虛擬記憶體機制出現以前,作業系統使用區塊快取系列,但是在虛擬記憶體出現以後,作業系統管理IO的粒度更大,因此採用了頁快取機制,頁快取是基於頁的、面向檔案的快取機制。

頁快取的讀取

Linux系統在讀取檔案時,會優先從頁快取讀取檔案內容,如果頁快取不存在,系統會先從磁碟讀取檔案內容更新到頁快取中,然後再從頁面快取讀取檔案內容並返回。

大致過程如下:

  • 進程呼叫函式庫函數read發起讀取檔請求

  • 核心檢查已開啟的文件列表,呼叫檔案系統提供的read介面

  • 找到檔案對應的inode,然後計算要讀取的具體的頁

  • ##透過inode查找對應的頁緩存,1)如果頁緩存節點命中,則直接返回文件內容;2)如果沒有對應的頁緩存,則會產生一個缺頁異常(page fault)。這時系統會建立新的空的頁面快取並從磁碟中讀取檔案內容,更新頁緩存,然後重複第4步

  • 讀取檔案返回

#所以說,所有的文件內容的讀取,無論最初有沒有命中頁緩存,最終都是直接來自頁緩存。

頁快取的寫入

因為頁快取的存在,當一個行程呼叫write時,檔案的更新只是被寫到了檔案的頁快取中,讓後將對應的頁標記為dirty,整個過程就結束了。 Linux核心會在週期性地將髒頁寫回磁碟,然後清理掉dirty標識。

由於寫入作業只會將變更寫入頁緩存,因此進程並不會因此為阻塞直到磁碟IO發生,如果此時電腦崩潰,寫入作業的變更可能並沒有發生在磁碟上。所以對於一些要求比較嚴格的寫入操作,例如資料系統,就需要主動呼叫fsync等操作及時將變更同步到磁碟上。讀取操作則不同,read通常會阻塞直到進程讀取到數據,而為了減少讀取操作的這種延遲,Linux系統還是用了「預讀」的技術,也就是從磁碟讀取資料時,核心將會多讀取一些頁到頁快取中。

回寫線程

頁快取的回寫是由核心中的單獨的執行緒來完成的,回寫執行緒會在以下3種情況下進行回寫:
  • 當空閒記憶體低於閾值時。當空閒記憶體不足時,需要釋放掉一部分緩存,由於只有不髒的頁才能被釋放,所以需要把髒頁都回寫到磁碟,使其變為可回收的乾淨的頁。
  • 髒頁在記憶體中處理時間超過閾值時。這是為了確保髒頁不會無限期的留在記憶體中,減少資料遺失的風險。
  • 當使用者程序呼叫sync和fsync系統呼叫時。這是為了提供使用者進程強制回寫的方法,滿足回寫要求嚴格的使用情境。

回寫線程的實作###
名稱 版本 說明
bdflush 2.6版本以前 bdflush 核心線程在後台運行,系統中只有一個bdflush 線程,當記憶體消耗到特定閥值以下時,bdflush 線程被喚醒。 kupdated 週期性的運行,寫回髒頁。但是整個系統僅僅只有一個 bdflush 線程,當系統回寫任務較重時,bdflush 線程可能會阻塞在某個磁碟的I/O上,導致其他磁碟的I/O回寫操作不能及時執行。
pdflush 2.6版本引入 pdflush 執行緒數目是動態的,取決於系統的I/O負載。它是面向系統中所有磁碟的全域任務的。但由於 pdflush 是面向所有磁碟的,所以有可能出現多個 pdflush 執行緒全部阻塞在某個擁塞的磁碟上,同樣導致其他磁碟的I/O回寫不能及時執行。
flusher執行緒 2.6.32版本以後引入 flusher 執行緒的數目不是唯一的,同時flusher執行緒不是針對所有磁碟的,而是每個flusher執行緒對應一個磁碟

頁快取的回收

Linux中頁快取的替換邏輯是一個修改過的LRU實現,也稱為雙股策略。和以前不同,Linux維護的不再是一個LRU鍊錶,而是維護兩個鍊錶:活躍鍊錶和非活躍鍊錶。處於活躍鍊錶上的頁面被認為是「熱」的且不會被換出,而在非活躍鍊錶上的頁面則是可以被換出的。在活躍鍊錶中的頁面必須在其被存取時就處於非活躍鍊錶中。兩個鍊錶都被偽LRU規則維護:頁面從尾部加入,從頭部移除,如同隊列。兩個鍊錶需要維持平衡–如果活躍鍊錶變得過多而超過了非活躍鍊錶,那麼活躍鍊錶的頭頁將被重新移回到非活躍鍊錶中,一遍能再被回收。雙鍊錶策略解決了傳統LRU演算法中對僅一次訪問的窘境。而且也更加簡單​​的實作了偽LRU語意。這種雙鍊錶方式也稱為LRU/2。更普遍的是n個鍊錶,故稱LRU/n。

【推薦學習:《linux影片教學》】

#總結

在這次遇到的線上故障中,根本原因在於在業務邏輯中使用了臨時文件做緩存,一個臨時文件創建後如果在短時間內刪除,這時候對這個文件的操作都是在頁緩存內進行,不會實際回寫到磁碟。當程式出現問題回應變慢時,臨時檔案存活時間變長,就可能會使其被回寫到磁碟上,導致磁碟壓力過大,進而影響整個系統。

以上是總結Linux磁碟快取相關知識的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:juejin.im。如有侵權,請聯絡admin@php.cn刪除