一文搞懂磁盤 I/O,基礎(chǔ)掃盲來了!
計算機的運行,就像一場有條不紊的交響樂演奏,CPU、內(nèi)存、磁盤等硬件各司其職,共同奏響和諧的旋律。在這場演奏中,磁盤 I/O 雖然不像 CPU 那樣被眾人熟知,卻承擔(dān)著至關(guān)重要的角色。它就像一座橋梁,連接著計算機的內(nèi)部世界與外部存儲,負責(zé)數(shù)據(jù)的輸入與輸出。從打開一份文檔,到加載一款大型游戲,再到服務(wù)器處理海量數(shù)據(jù),每一個操作都離不開磁盤 I/O 的默默支持。
然而,你是否想過,為什么有時候打開一個文件會瞬間完成,而有時候卻要等待許久?為什么同樣是存儲設(shè)備,固態(tài)硬盤和機械硬盤的讀寫速度會有天壤之別?磁盤 I/O 背后,究竟隱藏著怎樣的奧秘?
接下來,就讓我們一同深入探索磁盤 I/O 的世界,揭開它神秘的面紗,了解它的工作原理、性能指標(biāo),以及影響它的關(guān)鍵因素,讓你對計算機的存儲系統(tǒng)有全新的認知 。
一、磁盤I/O是什么?
磁盤是可以持久化存儲的設(shè)備,根據(jù)存儲介質(zhì)的不同,常見磁盤可以分為兩類:機械磁盤和固態(tài)磁盤。
第一類,機械磁盤,也稱為硬盤驅(qū)動器(Hard Disk Driver),通??s寫為 HDD。機械磁盤主要由盤片和讀寫磁頭組成,數(shù)據(jù)就存儲在盤片的環(huán)狀磁道中。在讀寫數(shù)據(jù)前,需要移動讀寫磁頭,定位到數(shù)據(jù)所在的磁道,然后才能訪問數(shù)據(jù)。顯然,如果 I/O 請求剛好連續(xù),那就不需要磁道尋址,自然可以獲得最佳性能。這其實就是我們熟悉的,連續(xù) I/O 的工作原理。與之相對應(yīng)的,當(dāng)然就是隨機 I/O,它需要不停地移動磁頭,來定位數(shù)據(jù)位置,所以讀寫速度就會比較慢。
第二類,固態(tài)磁盤(Solid State Disk),通??s寫為 SSD,由固態(tài)電子元器件組成。固態(tài)磁盤不需要磁道尋址,所以,不管是連續(xù) I/O,還是隨機 I/O 的性能,都比機械磁盤要好得多。
其實,無論機械磁盤,還是固態(tài)磁盤,相同磁盤的隨機 I/O 都要比連續(xù) I/O 慢很多,原因也很明顯。
- 對機械磁盤來說,我們剛剛提到過的,由于隨機 I/O 需要更多的磁頭尋道和盤片旋轉(zhuǎn),它的性能自然要比連續(xù) I/O 慢。
- 而對固態(tài)磁盤來說,雖然它的隨機性能比機械硬盤好很多,但同樣存在“先擦除再寫入”的限制。隨機讀寫會導(dǎo)致大量的垃圾回收,所以相對應(yīng)的,隨機 I/O 的性能比起連續(xù) I/O 來,也還是差了很多。
- 此外,連續(xù) I/O 還可以通過預(yù)讀的方式,來減少 I/O 請求的次數(shù),這也是其性能優(yōu)異的一個原因。很多性能優(yōu)化的方案,也都會從這個角度出發(fā),來優(yōu)化 I/O 性能
此外,機械磁盤和固態(tài)磁盤還分別有一個最小的讀寫單位。
- 機械磁盤的最小讀寫單位是扇區(qū),一般大小為 512 字節(jié)。
- 而固態(tài)磁盤的最小讀寫單位是頁,通常大小是 4KB、8KB 等。
如果每次都讀寫 512 字節(jié)這么小的單位的話,效率很低。所以,文件系統(tǒng)會把連續(xù)的扇區(qū)或頁,組成邏輯塊,然后以邏輯塊作為最小單元來管理數(shù)據(jù)。常見的邏輯塊的大小是 4KB,也就是說,連續(xù) 8 個扇區(qū),或者單獨的一個頁,都可以組成一個邏輯塊。
除了可以按照存儲介質(zhì)來分類,另一個常見的分類方法,是按照接口來分類,比如可以把硬盤分為 IDE(Integrated Drive Electronics)、SCSI(Small Computer System Interface) 、SAS(Serial Attached SCSI) 、SATA(Serial ATA) 、FC(Fibre Channel) 等。
不同的接口,往往分配不同的設(shè)備名稱。比如, IDE 設(shè)備會分配一個 hd 前綴的設(shè)備名,SCSI 和 SATA 設(shè)備會分配一個 sd 前綴的設(shè)備名。如果是多塊同類型的磁盤,就會按照 a、b、c 等的字母順序來編號;除了磁盤本身的分類外,當(dāng)你把磁盤接入服務(wù)器后,按照不同的使用方式,又可以把它們劃分為多種不同的架構(gòu)。
最簡單的,就是直接作為獨立磁盤設(shè)備來使用。這些磁盤,往往還會根據(jù)需要,劃分為不同的邏輯分區(qū),每個分區(qū)再用數(shù)字編號。比如我們前面多次用到的 /dev/sda ,還可以分成兩個分區(qū) /dev/sda1 和 /dev/sda2。
另一個比較常用的架構(gòu),是把多塊磁盤組合成一個邏輯磁盤,構(gòu)成冗余獨立磁盤陣列,也就是 RAID(Redundant Array of Independent Disks),從而可以提高數(shù)據(jù)訪問的性能,并且增強數(shù)據(jù)存儲的可靠性;根據(jù)容量、性能和可靠性需求的不同,RAID 一般可以劃分為多個級別,如 RAID0、RAID1、RAID5、RAID10 等。
- RAID0 有最優(yōu)的讀寫性能,但不提供數(shù)據(jù)冗余的功能。
- 而其他級別的 RAID,在提供數(shù)據(jù)冗余的基礎(chǔ)上,對讀寫性能也有一定程度的優(yōu)化。
最后一種架構(gòu),是把這些磁盤組合成一個網(wǎng)絡(luò)存儲集群,再通過 NFS、SMB、iSCSI 等網(wǎng)絡(luò)存儲協(xié)議,暴露給服務(wù)器使用。
其實在 Linux 中,磁盤實際上是作為一個塊設(shè)備來管理的,也就是以塊為單位讀寫數(shù)據(jù),并且支持隨機讀寫。每個塊設(shè)備都會被賦予兩個設(shè)備號,分別是主、次設(shè)備號。主設(shè)備號用在驅(qū)動程序中,用來區(qū)分設(shè)備類型;而次設(shè)備號則是用來給多個同類設(shè)備編號。
簡單來說,磁盤 I/O 就是計算機與磁盤之間進行數(shù)據(jù)輸入和輸出的過程。當(dāng)你在電腦上保存一個文檔時,這就是一個數(shù)據(jù)輸出(寫入)到磁盤的操作;而當(dāng)你打開這個文檔時,就是從磁盤輸入(讀?。?shù)據(jù)到計算機內(nèi)存的過程。磁盤就像是一個倉庫,而 I/O 操作則是貨物進出倉庫的搬運工作。
二、磁盤的結(jié)果與工作原理
我們可以把 Linux 存儲系統(tǒng)的 I/O 棧,由上到下分為三個層次,分別是文件系統(tǒng)層、通用塊層和設(shè)備層。這三個 I/O 層的關(guān)系如下圖所示,這其實也是 Linux 存儲系統(tǒng)的 I/O 棧全景圖:
圖片
據(jù)這張 I/O 棧的全景圖,我們可以更清楚地理解,存儲系統(tǒng) I/O 的工作原理。
- 文件系統(tǒng)層,包括虛擬文件系統(tǒng)和其他各種文件系統(tǒng)的具體實現(xiàn)。它為上層的應(yīng)用程序,提供標(biāo)準(zhǔn)的文件訪問接口;對下會通過通用塊層,來存儲和管理磁盤數(shù)據(jù)。
- 通用塊層,包括塊設(shè)備 I/O 隊列和 I/O 調(diào)度器。它會對文件系統(tǒng)的 I/O 請求進行排隊,再通過重新排序和請求合并,然后才要發(fā)送給下一級的設(shè)備層。
- 設(shè)備層,包括存儲設(shè)備和相應(yīng)的驅(qū)動程序,負責(zé)最終物理設(shè)備的 I/O 操作。
存儲系統(tǒng)的 I/O ,通常是整個系統(tǒng)中最慢的一環(huán)。所以, Linux 通過多種緩存機制來優(yōu)化 I/O 效率;比方說,為了優(yōu)化文件訪問的性能,會使用頁緩存、索引節(jié)點緩存、目錄項緩存等多種緩存機制,以減少對下層塊設(shè)備的直接調(diào)用。同樣,為了優(yōu)化塊設(shè)備的訪問效率,會使用緩沖區(qū),來緩存塊設(shè)備的數(shù)據(jù)。
- 平時調(diào)用write的時候,數(shù)據(jù)是從應(yīng)用寫入到了C標(biāo)準(zhǔn)庫的IO Buffer(用戶態(tài)),這個Buffer在應(yīng)用內(nèi)存中,應(yīng)用掛了,數(shù)據(jù)就沒了;
- 在關(guān)閉流之前調(diào)用flush,通過flush將數(shù)據(jù)主動寫入到內(nèi)核的Page Cache中,應(yīng)用掛了,數(shù)據(jù)也安全(內(nèi)核態(tài)),但是系統(tǒng)掛了數(shù)據(jù)就沒了;
將內(nèi)核中的Page Cache中的數(shù)據(jù)寫入到磁盤(緩存)中,系統(tǒng)掛了,數(shù)據(jù)也不丟失,需要調(diào)用fsync(持久化介質(zhì))。
總體來說,這就是操作系統(tǒng)的多級緩存和數(shù)據(jù)的可用性。操作系統(tǒng)也是程序,靠著多線程、異步、多級緩存實現(xiàn)高性能。
三、磁盤I/O的性能指標(biāo)
機械硬盤的連續(xù)讀寫性能很好,但隨機讀寫性能很差,這主要是因為磁頭移動到正確的磁道上需要時間,隨機讀寫時,磁頭需要不停的移動,時間都浪費在了磁頭尋址上,所以性能不高。衡量磁盤的重要主要指標(biāo)是IOPS和吞吐量。
(1)吞吐量
吞吐量(Throughput),指單位時間內(nèi)可以成功傳輸?shù)臄?shù)據(jù)數(shù)量。順序讀寫頻繁的應(yīng)用,如視頻點播,關(guān)注連續(xù)讀寫性能、數(shù)據(jù)吞吐量是關(guān)鍵衡量指標(biāo)。它主要取決于磁盤陣列的架構(gòu),通道的大小以及磁盤的個數(shù)。不同的磁盤陣列存在不同的架構(gòu),但他們都有自己的內(nèi)部帶寬,一般情況下,內(nèi)部帶寬都設(shè)計足夠充足,不會存在瓶頸。磁盤陣列與服務(wù)器之間的數(shù)據(jù)通道對吞吐量影響很大,比如一個2Gbps的光纖通道,其所能支撐的最大流量僅為250MB/s。最后,當(dāng)前面的瓶頸都不再存在時,硬盤越多的情況下吞吐量越大。
(2)IOPS
IOPS(Input/Output Per Second)即每秒的輸入輸出量(或讀寫次數(shù)),即指每秒內(nèi)系統(tǒng)能處理的I/O請求數(shù)量。隨機讀寫頻繁的應(yīng)用,如小文件存儲等,關(guān)注隨機讀寫性能,IOPS是關(guān)鍵衡量指標(biāo)??梢酝扑愠龃疟P的IOPS = 1000ms / (Tseek + Trotation + Transfer),如果忽略數(shù)據(jù)傳輸時間,理論上可以計算出隨機讀寫最大的IOPS。
常見磁盤的隨機讀寫最大IOPS為:
- 7200rpm的磁盤 IOPS = 76 IOPS
- 10000rpm的磁盤IOPS = 111 IOPS
- 15000rpm的磁盤IOPS = 166 IOPS
(3)響應(yīng)時間
響應(yīng)時間是指從發(fā)出 I/O 請求到收到響應(yīng)的時間間隔。它包括了尋道時間(機械硬盤)、旋轉(zhuǎn)延遲(機械硬盤)以及數(shù)據(jù)傳輸時間等。響應(yīng)時間越短,用戶體驗就越好,比如打開文件的速度就越快。
四、影響磁盤I/O的性能因素
Linux 磁盤 I/O 性能受多種因素影響,包括硬件設(shè)備、文件系統(tǒng)、系統(tǒng)配置和應(yīng)用程序的 I/O 模式等。以下是一些主要的影響因素:
(1)硬件設(shè)備
硬件是磁盤 I/O 性能的基礎(chǔ),包括硬盤的類型(HDD 或 SSD)、轉(zhuǎn)速、緩存大小以及接口類型(如 SATA、NVMe)等。
# 查看磁盤信息
lsblk
(2)文件系統(tǒng)
文件系統(tǒng)的選擇和配置對 I/O 性能有顯著影響。EXT4、XFS 和 Btrfs 是 Linux 中常用的文件系統(tǒng),每個文件系統(tǒng)都有其特點和最佳使用場景。
# 查看文件系統(tǒng)類型
df -T
(3)系統(tǒng)配置
Linux 內(nèi)核參數(shù)、I/O 調(diào)度器、文件系統(tǒng)的掛載選項等系統(tǒng)配置都會影響磁盤 I/O 性能。
# 查看當(dāng)前I/O調(diào)度器
cat /sys/block/sda/queue/scheduler
(4)應(yīng)用程序 I/O 模式
應(yīng)用程序的 I/O 模式,包括 I/O 大小、讀寫比例、同步異步 I/O 等,也會對磁盤 I/O 性能產(chǎn)生影響。示例代碼:C語言中同步和異步I/O的簡單比較
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
// 同步I/O操作
FILE *fp = fopen("testfile", "w+");
fprintf(fp, "Data to write");
fclose(fp);
// 異步I/O操作(在此示例中僅示意,實際實現(xiàn)更復(fù)雜)
// ...
return 0;
}
五、磁盤I/O性能評估工具
為了準(zhǔn)確評估磁盤 I/O 性能,選擇合適的工具至關(guān)重要。以下是一些常用的磁盤 I/O 性能評估工具及其使用方法。
(1)iostat是一個用于監(jiān)控系統(tǒng)輸入 / 輸出設(shè)備和 CPU 使用的工具,可以提供磁盤讀寫速度、I/O 操作次數(shù)等關(guān)鍵性能指標(biāo)
# 安裝iostat(以CentOS為例)
sudo yum install sysstat
# 使用iostat查看磁盤I/O性能
iostat -mx 1
(2)iotop是一個用來監(jiān)視 I/O 使用情況的工具,可以顯示哪些進程正在使用磁盤,以及它們的 I/O 速率。
# 安裝iotop(以CentOS為例)
sudo yum install iotop
# 使用iotop監(jiān)視I/O使用情況
iotop -o
(3)dd是一個經(jīng)典的命令行工具,用于復(fù)制文件并轉(zhuǎn)換和格式化數(shù)據(jù)。它也可以用來測試磁盤的讀寫性能。
# 使用dd命令測試寫性能
dd if=/dev/zero of=testfile bs=1M count=1024 oflag=dsync
# 使用dd命令測試讀性能
dd if=testfile of=/dev/null bs=1M count=1024 iflag=nocache
(4)fio是一個靈活的 I/O 測試工具,可以生成各種不同類型的負載,以測試磁盤的 I/O 性能。
# 使用fio進行磁盤I/O測試
fio --name=test --ioengine=libaio --iodepth=4 --rw=readwrite --bs=4k --size=1G --numjobs=1
通過使用這些工具,可以收集磁盤 I/O 性能的相關(guān)數(shù)據(jù),為進一步的性能優(yōu)化提供依據(jù);應(yīng)用程序在進行 I/O 操作時,可以采用異步 I/O、緩存等技術(shù),減少 I/O 等待時間,提高整體性能。
六、磁盤緩存與I/O緩存策略
磁盤緩存和 I/O 緩存策略是提升磁盤 I/O 性能的重要手段。合理配置和使用緩存,可以顯著減少磁盤的物理讀寫次數(shù),加快數(shù)據(jù)訪問速度。
6.1 磁盤緩存
磁盤緩存是位于硬盤和內(nèi)存之間的小容量高速存儲區(qū)域,它可以臨時存儲頻繁訪問的數(shù)據(jù),以減少對硬盤的訪問次數(shù)。
(1)啟用磁盤緩存
大多數(shù)現(xiàn)代硬盤都帶有內(nèi)置緩存,通常情況下操作系統(tǒng)會自動管理這些緩存。在某些情況下,管理員可能需要調(diào)整緩存策略。
# 查看磁盤緩存策略
hdparm -c /dev/sda
# 啟用磁盤緩存(對于支持此功能的硬盤)
hdparm -W 1 /dev/sda
(2)監(jiān)控磁盤緩存效果
監(jiān)控磁盤緩存的效果可以幫助管理員了解緩存的使用情況和性能改進。
# 使用iostat監(jiān)控磁盤緩存命中率
iostat -dx 1
6.2 I/O 緩存策略
I/O 緩存策略涉及操作系統(tǒng)如何使用內(nèi)存作為緩存來優(yōu)化磁盤 I/O 操作。Linux 提供了多種機制來管理 I/O 緩存。
(1)調(diào)整文件系統(tǒng)緩存,通過調(diào)整 vm.dirty_ratio 和 vm.dirty_background_ratio 參數(shù),可以控制文件系統(tǒng)緩存的大小和寫入策略。
# 查看當(dāng)前緩存參數(shù)
cat /proc/sys/vm/dirty_ratio
cat /proc/sys/vm/dirty_background_ratio
# 調(diào)整緩存參數(shù)
echo 20 > /proc/sys/vm/dirty_ratio
echo 10 > /proc/sys/vm/dirty_background_ratio
(2)使用直接 I/O,直接 I/O 允許應(yīng)用程序繞過操作系統(tǒng)緩存,直接向磁盤寫入數(shù)據(jù)。這在某些場景下可以提高性能,但也會增加磁盤 I/O 的壓力。
# 使用dd命令進行直接I/O操作
dd if=/dev/zero of=testfile bs=1M count=1024 oflag=dsync
(3)異步 I/O 與緩存,異步 I/O 可以與緩存策略結(jié)合使用,以提高應(yīng)用程序的響應(yīng)性和磁盤 I/O 效率。
// 示例代碼:結(jié)合異步I/O和緩存策略
#include <stdio.h>
#include <stdlib.h>
#include <aio.h>
int main() {
struct aiocb aiocb;
// 初始化異步I/O控制塊,并設(shè)置異步操作標(biāo)志...
// 執(zhí)行異步I/O操作...
aio_read(&aiocb);
// 處理其他任務(wù),操作系統(tǒng)會在后臺處理I/O操作...
// 等待異步操作完成...
aio_wait(&aiocb);
return 0;
}
通過合理配置磁盤緩存和 I/O 緩存策略,可以顯著提升 Linux 系統(tǒng)的磁盤 I/O 性能,尤其是在高負載和頻繁訪問的數(shù)據(jù)場景中。管理員需要根據(jù)具體的應(yīng)用需求和系統(tǒng)負載,調(diào)整和優(yōu)化緩存策略。
七、磁盤陣列與RAID技術(shù)
磁盤陣列技術(shù)通過將多個物理磁盤組合成一個邏輯單元來提高存儲系統(tǒng)的性能和可靠性。RAID(Redundant Array of Independent Disks)是一種常見的磁盤陣列實現(xiàn),它通過不同的數(shù)據(jù)分布和冗余策略來提升磁盤 I/O 性能和數(shù)據(jù)安全性。
7.1 RAID 級別
RAID 有多種級別,每種級別都有其特定的性能和冗余特點。以下是一些常見的 RAID 級別:
(1)RAID 0:通過數(shù)據(jù)條帶化(striping)來提高讀寫速度,但不提供數(shù)據(jù)冗余。它適用于需要高速存儲但數(shù)據(jù)安全性不高的場景。
# 創(chuàng)建RAID 0設(shè)備(需要mdadm工具)
mdadm --create /dev/md0 --level=0 --raid-devices=2 /dev/sda /dev/sdb
(2)RAID 1:通過鏡像(mirroring)來實現(xiàn)數(shù)據(jù)冗余,提高了數(shù)據(jù)的可靠性,但空間利用率只有 50%。它適用于對數(shù)據(jù)安全性要求高的場景。
# 創(chuàng)建RAID 1設(shè)備
mdadm --create /dev/md1 --level=1 --raid-devices=2 /dev/sda /dev/sdb
(3)RAID 5:結(jié)合了條帶化和分布式奇偶校驗,提供了性能提升和數(shù)據(jù)冗余。它適用于需要平衡性能和冗余的場景。
# 創(chuàng)建RAID 5設(shè)備
mdadm --create /dev/md5 --level=5 --raid-devices=3 /dev/sda /dev/sdb /dev/sdc
(4)RAID 10:
RAID 10 是 RAID 1 和 RAID 0 的組合,提供了高性能和數(shù)據(jù)冗余。它適用于對性能和數(shù)據(jù)安全性都有較高要求的場景。
# 創(chuàng)建RAID 10設(shè)備
mdadm --create /dev/md10 --level=10 --raid-devices=4 /dev/sda /dev/sdb /dev/sdc /dev/sdd
7.2 管理 RAID 設(shè)備
使用 mdadm
工具可以管理 RAID 設(shè)備,包括創(chuàng)建、監(jiān)控和修復(fù) RAID 陣列。
# 查看RAID設(shè)備狀態(tài)
cat /proc/mdstat
# 修復(fù)RAID設(shè)備(如果某個磁盤出現(xiàn)問題)
mdadm --manage /dev/md0 --rebuild-map
7.3 監(jiān)控 RAID 性能
監(jiān)控 RAID 性能對于確保存儲系統(tǒng)的高效運行至關(guān)重要。可以使用 iostat
、mdstat
和其他工具來監(jiān)控 RAID 設(shè)備的性能。
# 使用iostat監(jiān)控RAID設(shè)備性能
iostat -dxm /dev/md0 1
7.4 RAID 與磁盤 I/O 性能
RAID 技術(shù)可以顯著提升磁盤 I/O 性能,尤其是在讀寫操作上。選擇合適的 RAID 級別和配置對于最大化性能至關(guān)重要。同時,合理的 RAID 配置也可以提高數(shù)據(jù)的可靠性和容錯能力。
通過使用磁盤陣列和 RAID 技術(shù),系統(tǒng)管理員可以提升 Linux 系統(tǒng)的磁盤 I/O 性能,同時確保數(shù)據(jù)的安全性和可靠性。在選擇 RAID 級別時,需要綜合考慮性能需求、數(shù)據(jù)冗余要求和成本等因素。