1. 程式人生 > 其它 >Linux效能優化-磁碟I/O是怎麼工作的(上)

Linux效能優化-磁碟I/O是怎麼工作的(上)

檔案系統是對儲存裝置上的檔案,進行組織管理的一種機制。而Linux在各種檔案系統實現上,又抽象了一層虛擬檔案系統VFS,它定義的一組所有檔案系統都支援的資料結構和標準介面。

這樣,對應用程式來說,只需要跟VFS提供的統一介面互動,而不需要關注檔案系統的具體實現;對具體的檔案來說,只需要按照VFS的標準,就可以無縫支援各種應用程式。

VFS內部又通過目錄項、索引節點、邏輯塊以及超級邏輯塊等資料結構,來管理檔案。

  • 目錄項:記錄了檔案的名字,以及檔案與其他目錄項之間的目錄關係
  • 索引節點:記錄了檔案的元資料
  • 邏輯塊:是由連線磁碟扇區構成的最小邏輯單元,用來儲存檔案資料
  • 超級塊:用來記錄檔案系統整體的狀態,如索引節點和邏輯塊的使用情況等。

其中,目錄項是一個記憶體快取;而超級塊、索引節點和邏輯塊都是儲存在磁碟的持久化資料。

磁碟

磁碟是可以持久化儲存的裝置,根據儲存介質的不同,常見磁碟可以分為兩類:機械磁碟和固態磁碟。

第一類,機械磁碟,也稱為硬碟驅動器(Hard Disk Driver),通常縮寫為 HDD。機械磁碟主要由碟片和讀寫磁頭組成,資料就儲存在碟片的環狀磁軌中。在讀寫資料前,需要移動讀寫磁頭,定位到資料所在的磁軌,然後才能訪問資料。

顯然,如果 I/O 請求剛好連續,那就不需要磁軌定址,自然可以獲得最佳效能。這其實就是我們熟悉的,連續 I/O 的工作原理。與之相對應的,當然就是隨機 I/O,它需要不停地移動磁頭,來定位資料位置,所以讀寫速度就會比較慢。

第二類,固態磁碟(Solid State Disk),通常縮寫為 SSD,由固態電子元器件組成。固態磁碟不需要磁軌定址,所以,不管是連續 I/O,還是隨機 I/O 的效能,都比機械磁碟要好得多。

其實,無論機械磁碟,還是固態磁碟,相同磁碟的隨機 I/O 都要比連續 I/O 慢很多,原因也很明顯。

  • 對機械磁碟來說,我們剛剛提到過的,由於隨機 I/O 需要更多的磁頭尋道和碟片旋轉,它的效能自然要比連續 I/O 慢。
  • 而對固態磁碟來說,雖然它的隨機效能比機械硬碟好很多,但同樣存在“先擦除再寫入”的限制。隨機讀寫會導致大量的垃圾回收,所以相對應的,隨機 I/O 的效能比起連續 I/O 來,也還是差了很多。
  • 此外,連續 I/O 還可以通過預讀的方式,來減少 I/O 請求的次數,這也是其效能優異的一個原因。很多效能優化的方案,也都會從這個角度出發,來優化 I/O 效能。

此外,機械磁碟和固態磁碟還分別有一個最小的讀寫單位。

  • 機械磁碟的最小讀寫單位是扇區,一般大小為 512 位元組。
  • 而固態磁碟的最小讀寫單位是頁,通常大小是 4KB、8KB 等。

如果每次都讀寫 512 位元組這麼小的單位的話,效率很低。所以,檔案系統會把連續的扇區或頁,組成邏輯塊,然後以邏輯塊作為最小單元來管理資料。常見的邏輯塊的大小是 4KB,也就是說,連續 8 個扇區,或者單獨的一個頁,都可以組成一個邏輯塊。

通用塊層

跟虛擬檔案系統 VFS 類似,為了減小不同塊裝置的差異帶來的影響,Linux 通過一個統一的通用塊層,來管理各種不同的塊裝置。

通用塊層,其實是處在檔案系統和磁碟驅動中間的一個塊裝置抽象層。它主要有兩個功能 。

第一個功能跟虛擬檔案系統的功能類似。向上,為檔案系統和應用程式,提供訪問塊裝置的標準介面;向下,把各種異構的磁碟裝置抽象為統一的塊裝置,並提供統一框架來管理這些裝置的驅動程式。

第二個功能,通用塊層還會給檔案系統和應用程式發來的 I/O 請求排隊,並通過重新排序、請求合併等方式,提高磁碟讀寫的效率。

其中,對 I/O 請求排序的過程,也就是我們熟悉的 I/O 排程。事實上,Linux 核心支援四種 I/O 排程演算法,分別是 NONE、NOOP、CFQ 以及 DeadLine。

第一種 NONE ,更確切來說,並不能算 I/O 排程演算法。因為它完全不使用任何 I/O 排程器,對檔案系統和應用程式的 I/O 其實不做任何處理,常用在虛擬機器中(此時磁碟 I/O 排程完全由物理機負責)。

第二種 NOOP ,是最簡單的一種 I/O 排程演算法。它實際上是一個先入先出的佇列,只做一些最基本的請求合併,常用於 SSD 磁碟。

第三種 CFQ(Completely Fair Scheduler),也被稱為完全公平排程器,是現在很多發行版的預設 I/O 排程器,它為每個程序維護了一個 I/O 排程佇列,並按照時間片來均勻分佈每個程序的 I/O 請求。類似於程序 CPU 排程,CFQ 還支援程序 I/O 的優先順序排程,所以它適用於執行大量程序的系統,像是桌面環境、多媒體應用等。

最後一種 DeadLine 排程演算法,分別為讀、寫請求建立了不同的 I/O 佇列,可以提高機械磁碟的吞吐量,並確保達到最終期限(deadline)的請求被優先處理。DeadLine 排程演算法,多用在 I/O 壓力比較重的場景,比如資料庫等。

I/O 棧

清楚了磁碟和通用塊層的工作原理,我們就可以整體來看 Linux 儲存系統的 I/O 原理了。我們可以把 Linux 儲存系統的 I/O 棧,由上到下分為三個層次,分別是檔案系統層、通用塊層和裝置層。這三個 I/O 層的關係如下圖所示,這其實也是 Linux 儲存系統的 I/O 棧全景圖。

根據這張 I/O 棧的全景圖,可以更清楚地理解,儲存系統 I/O 的工作原理。

  • 檔案系統層,包括虛擬檔案系統和其他各種檔案系統的具體實現。它為上層的應用程式,提供標準的檔案訪問介面;對下會通過通用塊層,來儲存和管理磁碟資料。
  • 通用塊層,包括塊裝置 I/O 佇列和 I/O 排程器。它會對檔案系統的 I/O 請求進行排隊,再通過重新排序和請求合併,然後才要傳送給下一級的裝置層。
  • 裝置層,包括儲存裝置和相應的驅動程式,負責最終物理裝置的 I/O 操作。儲存系統的 I/O ,通常是整個系統中最慢的一環。

所以, Linux 通過多種快取機制來優化 I/O 效率。比方說,為了優化檔案訪問的效能,會使用頁快取、索引節點快取、目錄項快取等多種快取機制,以減少對下層塊裝置的直接呼叫。

同樣,為了優化塊裝置的訪問效率,會使用緩衝區,來快取塊裝置的資料。