問題背景
iostat -xdm 1 通常用來查看機器磁盤IO的性能。
我們一般會有個經驗值,比如,ioutil要小於80%, svctm要小於2ms。
前幾天碰到一個奇怪的現象:有一台SSD機器,磁盤的iops在1萬多,吞吐量在100多M,看來壓力並不大,但是ioutil一直在90%以上。SSD的磁盤怎么會只能承受這么點壓力?
下面是當時tsar的數據:
針對這個問題的結論
- ioutil是繁忙度的一個度量(非空閑時間)。對於后面有多塊磁盤支撐的虛擬設備意義不大。所以對於SSD,並不能說ioutil到了100%了,磁盤就到達最大極限性能了。
官方文檔的描述
Percentage of elapsed time during which I/O requests were issued to the device (bandwidth utilization for the device).
Device saturation occurs when this value is close to 100% for devices serving requests serially.
But for devices serving requests in parallel, such as RAID arrays and modern SSDs,
this number does not reflect their performance limits.
-
await是平均IO響應時間,包括在驅動請求隊列里的等待和設備的IO響應時間(ms)。
-
svctm是一個推斷值。計算方法: svctm = ioutil/IOPS = ioutil/(rs+ws)
比如,在1s內,60%的使用率,有300的IOPS,那么平均服務時間svctm = 600ms/300 = 2ms
在未來某個版本的iostat會被刪除,官方文檔是這樣描述原因的。
官方文檔的描述
The average service time (svctm field) value is meaningless,
as I/O statistics are calculated at block level,
and we don’t know when the disk driver starts to process a request.
For this reason, this field will be removed in a future sysstat version.
Linux內核IO協議棧結構
Linux整體IO體系可以分為七層,它們分別是:
-
VFS層:虛擬文件系統層。由於內核要跟多種文件系統打交道,而每一種文件系統所實現的數據結構和相關方法都可能不盡相同,所以,內核抽象了這一層,專門用來適配各種文件系統,並對外提供統一操作接口。
-
文件系統層:不同的文件系統實現自己的操作過程,提供自己特有的特征。
-
頁緩存層:負責針對page的緩存。
-
通用塊層:由於絕大多數情況的io操作是跟塊設備打交道,所以Linux在此提供了一個類似vfs層的塊設備操作抽象層。下層對接各種不同屬性的塊設備,對上提供統一的Block IO請求標准。
-
IO調度層:因為絕大多數的塊設備都是類似磁盤這樣的設備,所以有必要根據這類設備的特點以及應用的不同特點來設置一些不同的調度算法和隊列。以便在不同的應用環境下有針對性的提高磁盤的讀寫效率,這里就是大名鼎鼎的Linux電梯所起作用的地方。針對機械硬盤的各種調度方法就是在這實現的。
-
塊設備驅動層:驅動層對外提供相對比較高級的設備操作接口,往往是C語言的,而下層對接設備本身的操作方法和規范。
-
塊設備層:這層就是具體的物理設備了,定義了各種真對設備操作方法和規范。
簡圖
還有一張更詳細的圖,圖上已有出處:
iostat是怎么計算的?
- /proc/diskstats 內核進行了多少IO,IO的耗時統計,都是會記錄在/proc/diskstats。
$cat /proc/diskstats | grep -w sdb
8 16 sdb 5599308471 607 262844839314 1688433460 18293450260 0 402591421472 167371198 4 3337033295 1847117638
格式:
前3列定位一個設備。這個文件是每毫秒更新一次。
- /sys/block/${device_name}/stat
這個文件記錄的內容實際上和/proc/diskstats 完全一樣的,只不過,這個文件只針對某個設備,或是分區,因此,只有一行內容,也比/proc/diskstats 少前3列,不用單獨定位一個設備。
$cat /sys/block/sdb/stat
5599363483 607 262845774770 1688449447 18294010908 0 402598669112 167535796 0 3337131224 1847298025
f1: read_IOs, 讀次數
f2: read_merges, 合並讀次數。比如,兩個地址連續的IO,真正下發到設備,會合並成一個IO
f3: read_sectors, 讀扇區的次數
f4: read_ticks, 讀花費的毫秒數
f5: write_IOs, 寫次數
f6: write_merges, 合並寫次數
f7: write_sectors, 寫扇區次數
f8: write_ticks, 寫操作花費的毫秒數
f9: in_flight, 正在處理的IO請求數,The number of I/Os currently in flight. It does not include I/O requests that are in the queue but not yet issued to the device driver.
f10: io_ticks, IO操作花費的毫秒數,每次隊列中有IO,就增加。This value counts the time during which the device has had I/O requests queued.
f11: time_in_queue, The number of I/Os in progress (field 9) times the number of milliseconds spent doing I/O since the last update of this field.