Linux 性能優化 - 磁盤 I-O 優化

  1. 文件系統

1.1. 文件系統工作原理

文件系統是在磁盤的基礎上,提供了一個用來管理文件的樹狀結構。

1.1.1. 索引節點和目錄項

在 Linux 中一切皆文件 , 文件系統, 本身是對存儲設備上的文件,進行組織管理的機制

爲了方便管理,Linux 文件系統爲每個文件都分配兩個數據結構, 索引節點(index node) 和 目錄項(directory entry) 。它們主要用來記錄文件的 元信息 和 目錄結構 。

文件數據到底是怎麼存儲的呢?

磁盤讀寫的最小單位是扇區,然而扇區只有 512B 大小,如果每次都讀寫這麼小的單位,效率一定很低。所以,文件系統又把連續的扇區組成了邏輯塊,然後每次都以邏輯塊爲最小單元,來管理數據。常見的邏輯塊大小爲 4KB,也就是由連續的 8 個扇區組成。

注意:

  1. 目錄項本身就是一個內存緩存,而索引節點則是存儲在磁盤中的數據 ,Buwer 和 Cache 緩存可以協調慢速磁盤與快速 CPU 的性能差異,文件內容會緩存到頁緩存 Cache 中 , 這些索引節點自然也會緩存到內存中,加速文件的訪問。

  2. 磁盤在執行文件系統格式化時,會被分成三個存儲區域, 超級塊 、 索引節點區 和 數據塊區 。

1.1.2. 虛擬文件系統

什麼是虛擬文件系統 VFS?

爲了支持各種不同的文件系統,Linux 內核在用戶進程和文件系統的中間,又引入了一個抽象層,也就是虛擬文件系統 VFS(Virtual File System)。VFS 定義了一組所有文件系統都支持的數據結構和標準接口。這樣,用戶進程和內核中的其他子系統,只需要跟 VFS 提供的統一接口進行交互就可以了,而不需要再關心底層各種文件系統的實現細節。

爲了更好地理解系統調用、VFS、緩存、文件系統以及塊存儲之間的關係 , 可以參考 Linux 文件系統的架構圖

通過這張圖可以看到,在 VFS 的下方,Linux 支持各種各樣的文件系統,如 Ext4、XFS、NFS 等等。按照存儲位置的不同,這些文件系統可以分爲三類。

這些文件系統,要先掛載到 VFS 目錄樹中的某個子目錄(稱爲掛載點),然後才能訪問其中的文件。拿第一類,也就是基於磁盤的文件系統爲例,在安裝系統時,要先掛載一個根目錄(/),在根目錄下再把其他文件系統(比如其他的磁盤分區、/proc 文件系統、/sys 文件系統、NFS 等)掛載進來。

  1. 磁盤 I/O 工作原理

2.1. 磁盤類型

2.1.1. 根據介質不同分類

磁盤是可以持久化存儲的設備,根據存儲介質的不同,常見磁盤可以分爲兩類:機械磁盤和固態磁盤。

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

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

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

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

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

2.1.2. 磁盤按照接口分類

按照接口來分類,比如可以把硬盤分爲 IDE(Integrated Drive Electronics) 、 SCSI(Small Computer System Interface) 、 SAS(Serial Attached SCSI) 、 SATA(Serial ATA) 、 FC(Fibre Channel)等。

不同的接口,往往分配不同的設備名稱。比如, IDE 設備會分配一個 hd 前綴的設備名,SCSI 和 SATA 設備會分配一個 sd 前綴的設備名。如果是多塊同類型的磁盤,就會按照 a、b、c 等的字母順序來編號。

2.1.3. 按照使用方式分類

把多塊磁盤組合成一個邏輯磁盤,構成冗餘獨立磁盤陣列,也就是 RAID(Redundant Array of Independent Disks),從而可以提高數據訪問的性能,並且增強數據存儲的可靠性。

根據容量、性能和可靠性需求的不同,RAID 一般可以劃分爲多個級別,如 RAID0、RAID1、RAID5、RAID10 等。RAID0 有最優的讀寫性能,但不提供數據冗餘的功能。

而其他級別的 RAID,在提供數據冗餘的基礎上,對讀寫性能也有一定程度的優化。

最後一種架構,是把這些磁盤組合成一個網絡存儲集羣,再通過 NFS、SMB、iSCSI 等網絡存儲協議,暴露給服務器使用。

在 Linux 中,磁盤實際上是作爲一個塊設備來管理的,也就是以塊爲單位讀寫數據,並且支持隨機讀寫。每個塊設備都會被賦予兩個設備號,分別是主、次設備號。主設備號用在驅動程序中,用來區分設備類型;而次設備號則是用來給多個同類設備編號。

2.2.IO 棧

Linux 的 IO 路徑可能是 Linux 系統中比較複雜的模塊,它直接決定了系統的性能。

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

應用程序:

通過相關係統調用 (如 open/read/write) 發起 IO 請求,屬於 IO 請求的源頭;

文件系統:

應用程序的請求直接到達文件系統層。文件系統又分爲 VFS 和具體文件系統(ext3、ext4 等),VFS 對應用層提供統一的訪問接口,而 ext3 等文件系統則實現了這些接口。另外,提高 IO 性能,在該層還實現了諸如 page cache 等功能。同時,用戶也可以選擇繞過 page cache,而是直接使用 direct 模式進行 IO(如數據庫)。

塊設備層:

文件系統將 IO 請求打包提交給塊設備層,該層會對這些 IO 請求作合併、排序、調度等,然後以新的格式發往更底層。在該層次上實現了多種電梯調度算法,如 cfq、deadline 等。

SCSI 層:

塊設備層將請求發往 SCSI 層,SCSI 就開始真實處理這些 IO 請求,但是 SCSI 層又對其內部按照功能劃分了不同層次: * SCSI 高層:高層驅動負責管理 disk,接收塊設備層發出的 IO 請求,打包成 SCSI 層可識別的命令格式,繼續往下發;SCSI 中層:中層負責通用功能,如錯誤處理,超時重試等; SCSI 低層:底層負責識別物理設備,將其抽象提供給高層,同時接收高層派發的 scsi 命令,交給物理設備處理。

  1. 性能指標

3.1. 磁盤 I/O 性能指標

我們需要了解磁盤 I/O 性能監控的指標,以及每個指標的所揭示的磁盤某方面的性能。磁盤 I/O 性能監控的指標主要包括:

1). 每秒 I/O 數( IOPS )

一次磁盤的連續讀或者連續寫稱爲一次磁盤 I/O, 磁盤的 IOPS 就是每秒磁盤連續讀次數和連續寫次數之和。

2). 吞吐量( Throughput)

指硬盤傳輸數據流的速度,傳輸數據爲讀出數據和寫入數據的和。

3). 平均 I/O 數據尺寸

平均 I/O 數據尺寸爲吞吐量除以 I/O 數目,該指標對揭示磁盤使用模式有重要意義。

4). 磁盤活動時間百分比( Utilization) %util

磁盤處於活動時間的百分比,即磁盤利用率,磁盤在數據傳輸和處理命令處於活動狀態。

5). 服務時間( ServiceTime) svctm

指磁盤讀或寫操作執行的時間,包括尋道,數據傳輸等時間。

6).I/O 等待隊列長度( Queue Length)

指待處理的 I/O 請求的數目,如果 I/O 請求壓力持續超出磁盤處理能力,該值將增加。

7). 等待時間( Wait Time)

指磁盤讀或寫操作等待執行的時間,即在隊列中排隊的時間。

3.2. 磁盤 I/O 觀測

iostat 是最常用的磁盤 I/O 性能觀測工具,它提供了每個磁盤的 使用率 、 IOPS 、 吞吐量 等各種常見的性能指標,當然,這些指標實際上來自 /proc/diskstats。

1.命令格式:iostat [參數][時間][次數]

2.常用參數:

  1. -c : 僅顯示 cpu 的狀態

  2. -d : 顯示磁盤使用情況,不可以和 -c 一起使用

  3. -k : 默認顯示的是讀入讀出的 block 信息,以 KB 爲單位顯示

  4. -m : 以 M 爲單位顯示

  5. -t : 顯示終端和 CPU 的信息

  6. -x : 顯示詳細信息

  7. 顯示所有磁盤 I/O 的指標

  1. 磁盤每一列的含義如下:

  1. 需要注意的指標

3.3. 進程 I/O 觀測

要觀察進程的 I/O 情況,還可以使用 pidstat 和 iotop 這兩個工具。

3.3.1.pidstat 觀測 I/O

pidstat 給它加上 -d 參數 (使用 - d 選項,可以查看進程 IO 的統計信息),就可以看到進程的 I/O 情況,如下所示:

$ pidstat -d 1
13:39:51 UID PID kB_rd/s kB_wr/s kB_ccwr/s iodelay Command
13:39:52 102 916 0.00    4.00    0.00      0       rsyslogd

從 pidstat 的輸出能看到,它可以實時查看每個進程的 I/O 情況,包括下面這些內容。

3.3.2.iotop 觀測 I/O

iotop 是一個類似於 top 的工具,可以按照 I/O 大小對進程排序,然後找到 I/O 較大的那些進程。如果沒有該命令,請通過 yum install iotop 進行安裝

從這個輸出可以看到,前兩行分別表示,進程的磁盤讀寫大小總數和磁盤真實的讀寫大小總數。因爲緩存、緩衝區、I/O 合併等因素的影響,它們可能並不相等。

剩下的部分,則是從各個角度來分別表示進程的 I/O 情況,包括線程 ID、I/O 優先級、每秒讀磁盤的大小、每秒寫磁盤的大小、換入和等待 I/O 的時鐘百分比等。

  1. 性能工具

第一個維度,從文件系統和磁盤 I/O 的性能指標出發。換句話說,當你想查看某個性能指標時,要清楚知道,哪些工具可以做到

第二個維度,從工具出發。也就是當你已經安裝了某個工具後,要知道這個工具能提供哪些指標。

根據工具查詢指標

  1. 磁盤 I/O 優化策略

5.1. 應用程序優化策略

  1. 可以用追加寫代替隨機寫,減少尋址開銷,加快 I/O 寫的速度。

  2. 可以藉助緩存 I/O ,充分利用系統緩存,降低實際 I/O 的次數。

  3. 可以在應用程序內部構建自己的緩存,或者用 Redis 這類外部緩存系統。

  4. 需要頻繁讀寫同一塊磁盤空間時,可以用 mmap 代替 read/write,減少內存的拷貝次數。

  5. 在需要同步寫的場景中,儘量將寫請求合併,而不是讓每個請求都同步寫入磁盤。

  6. 在多個應用程序共享相同磁盤時,爲了保證 I/O 不被某個應用完全佔用,推薦你使用 cgroups 的 I/O 子系統,來限制進程 / 進程組的 IOPS 以及吞吐量。

5.2. 文件系統優化策略

  1. 可以根據實際負載場景的不同,選擇最適合的文件系統。比如 Ubuntu 默認使用 ext4 文件系統,而 CentOS 7 默認使用 xfs 文件系統。

  2. 在選好文件系統後,還可以進一步優化文件系統的配置選項 。

  3. 可以優化文件系統的緩存 。

5.3. 磁盤優化策略

磁盤也是整個 I/O 棧的最底層。從磁盤角度出發,自然也有很多有效的性能優化方法

  1. 最簡單有效的優化方法,就是換用性能更好的磁盤,比如用 SSD 替代 HDD。

  2. 我們可以使用 RAID ,把多塊磁盤組合成一個邏輯磁盤,構成冗餘獨立磁盤陣列。這樣既可以提高數據的可靠性,又可以提升數據的訪問性能。

  3. 針對磁盤和應用程序 I/O 模式的特徵,我們可以選擇最適合的 I/O 調度算法。比方說,SSD 和虛擬機中的磁盤,通常用的是 noop 調度算法。而數據庫應用,我更推薦使用 deadline 算法。

  4. 我們可以對應用程序的數據,進行磁盤級別的隔離 。

  5. 在順序讀比較多的場景中,我們可以增大磁盤的預讀數據 。

  6. 我們可以優化內核塊設備 I/O 的選項。比如,可以調整磁盤隊列的長度, 以提升磁盤的吞吐量 。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/2b1a0TD6g-g5ikYFUHeO_g