windows下如何查看磁盤IO性能

windows下如何查看磁盤IO性能

通常,我們很容易觀察到數據庫服務器的內存和CPU壓力。但是對I/O壓力沒有直觀的判斷方法。

磁盤有兩個重要的參數:Seek time、Rotational  latency

正常的I/O計數爲:①1000/(Seek time+Rotational latency)*0.75,在此範圍內屬正常。當達到85%的I/O計數以上時則基本認爲已經存在I/O瓶頸。理論情況下,磁盤的隨機讀計數爲125、 順序讀計數爲225。對於數據文件而言是隨機讀寫,日誌文件是順序讀寫。因此,數據文件建議存放於RAID5上,而日誌文件存放於RAID10或 RAID1中。  

 

下面假設在有4塊硬盤的RAID5中觀察到的Physical Disk性能對象的部分值:  

 

Avg. DiskQueue Length 12  隊列長度

Avg. DiskSec/Read .035    讀數據所用時間ms

Avg. DiskSec/Write .045    寫數據所用時間ms

DiskReads/sec 320        每秒讀數據量

DiskWrites/sec 100        每秒寫數據量

Avg. DiskQueue Length,12/4=3,每塊磁盤的平均隊列建議不超過2。  

Avg. DiskSec/Read一般不要超過11~15ms。  

Avg. DiskSec/Write一般建議小於12ms。  

 

從上面的結果,我們看到磁盤本身的I/O能力是滿足我們的要求的,原因是因爲有大量的請求才導致隊列等待,這很可能是因爲你的SQL語句導致大量的表掃描所致。在進行優化後,如果還是不能達到要求,下面的公式可以幫助你計算使用幾塊硬盤可以滿足這樣的併發要求

Raid 0 -- I/Os per disk = (reads +writes) / number of disks

Raid 1 -- I/Os per disk = [reads +(2 * writes)] / 2

Raid 5 -- I/Os per disk = [reads +(4 * writes)] / number of disks

Raid 10 -- I/Os per disk = [reads +(2 * writes)] / number of disks  

 

我們得到的結果是:(320+400)/4=180,這時你可以根據公式①來得到磁盤的正常I/O值。假設現在正常I/O計數爲125,爲了達到這個結果:720/125=5.76。就是說要用6塊磁盤才能達到這樣的要求。  

 

但是上面的Disk Reads/sec和Disk Writes/sec是個很難正確估算的值。因此只能在系統比較忙時,大概估算一個平均值,作爲計算公式的依據。另一個是你很難從客戶那裏得到Seek time、 Rotational latency參數的值,這也只能用理論值125進行計算。

前言

作爲一個數據庫管理員,關注系統的性能是日常最重要的工作之一,而在所關注的各方面的性能只能IO性能卻是最令人頭痛的一塊,面對着各種生澀的參數和令人眼花繚亂的新奇的術語,再加上存儲廠商的忽悠,總是讓我們有種雲裏霧裏的感覺。本系列文章試圖從基本概念開始對磁盤存儲相關的各種概念進行綜合歸納,讓大家能夠對IO性能相關的基本概念,IO性能的監控和調整有個比較全面的瞭解。

在這一部分裏我們先捨棄各種結構複雜的存儲系統,直接研究一個單獨的磁盤的性能問題,藉此瞭解各個衡量IO系統系能的各個指標以及之間的關係。

幾個基本的概念

在研究磁盤性能之前我們必須先了解磁盤的結構,以及工作原理。不過在這裏就不再重複說明了,關係硬盤結構和工作原理的信息可以參考維基百科上面的相關詞條——Hard disk drive(英文)硬盤驅動器(中文)

讀寫IO(Read/Write IO)操作

磁盤是用來給我們存取數據用的,因此當說到IO操作的時候,就會存在兩種相對應的操作,存數據時候對應的是寫IO操作,取數據的時候對應的是讀IO操作

單個IO操作

控制磁盤的控制器接到操作系統的讀IO操作指令的時候,控制器就會給磁盤發出一個讀數據的指令,並同時將要讀取的數據塊的地址傳遞給磁盤,然後磁盤會將讀取到的數據傳給控制器,並由控制器返回給操作系統,完成一個寫IO的操作;同樣的,一個寫IO的操作也類似,控制器接到寫的IO操作的指令和要寫入的數據,並將其傳遞給磁盤,磁盤在數據寫入完成之後將操作結果傳遞迴控制器,再由控制器返回給操作系統,完成一個寫IO的操作。單個IO操作指的就是完成一個IO或者是讀IO的操作。

隨機訪問(Random Access)與連續訪問(Sequential Access)

隨機訪問指的是本次IO所給出的扇區地址和上次IO給出扇區地址相差比較大,這樣的話磁頭在兩次IO操作之間需要作比較大的移動動作才能重新開始讀/寫數據。相反的,如果當次IO給出的扇區地址與上次IO結束的扇區地址一致或者是接近的話,那磁頭就能很快的開始這次IO操作,這樣的多個IO操作稱爲連續訪問。因此儘管相鄰的兩次IO操作在同一時刻發出,但如果它們的請求的扇區地址相差很大的話也只能稱爲隨機訪問,而非連續訪問。

順序IO模式(Queue Mode)/併發IO模式(BurstMode)

磁盤控制器可能會一次對磁盤組發出一連串的IO命令,如果磁盤組一次只能執行一個IO命令時稱爲順序IO;當磁盤組能同時執行多個IO命令時,稱爲併發IO。併發IO只能發生在由多個磁盤組成的磁盤組上,單塊磁盤只能一次處理一個IO命令。

 

單個IO的大小(IO ChunkSize)

熟悉數據庫的人都會有這麼一個概念,那就是數據庫存儲有個基本的塊大小(Block Size),不管是SQL Server還是Oracle,默認的塊大小都是8KB,就是數據庫每次讀寫都是以8k爲單位的。那麼對於數據庫應用發出的固定8k大小的單次讀寫到了寫磁盤這個層面會是怎麼樣的呢,就是對於讀寫磁盤來說單個IO操作操作數據的大小是多少呢,是不是也是一個固定的值?答案是不確定。首先操作系統爲了提高 IO的性能而引入了文件系統緩存(File System Cache),系統會根據請求數據的情況將多個來自IO的請求先放在緩存裏面,然後再一次性的提交給磁盤,也就是說對於數據庫發出的多個8K數據塊的讀操作有可能放在一個磁盤讀IO裏就處理了。還有對於有些存儲系統也是提供了緩存(Cache)的,接收到操作系統的IO請求之後也是會將多個操作系統的 IO請求合併成一個來處理。不管是操作系統層面的緩存還是磁盤控制器層面的緩存,目的都只有一個,提高數據讀寫的效率。因此每次單獨的IO操作大小都是不一樣的,它主要取決於系統對於數據讀寫效率的判斷。

當一次IO操作大小比較小的時候我們成爲小的IO操作,比如說1K4K8K這樣的;當一次IO操作的數據量比較的的時候稱爲大IO操作,比如說32K64K甚至更大。

我們說到塊大小(Block Size)的時候通常我們會接觸到多個類似的概念,像我們上面提到的那個在數據庫裏面的數據最小的管理單位,Oralce稱之爲塊(Block),大小一般爲8KSQL Server稱之爲頁(Page),一般大小也爲8k。在文件系統裏面我們也能碰到一個文件系統的塊,在現在很多的Linux系統中都是4K(通過 /usr/bin/time -v可以看到),它的作用其實跟數據庫裏面的塊/頁是一樣的,都是爲了方便數據的管理。但是說到單次IO的大小,跟這些塊的大小都是沒有直接關係的,在英文裏單次IO大小通常被稱爲是IO Chunk Size,不會說成是IO Block Size的。

IOPS(IO per Second)

IOPSIO系統每秒所執行IO操作的次數,是一個重要的用來衡量系統IO能力的一個參數。對於單個磁盤組成的IO系統來說,計算它的IOPS不是一件很難的事情,只要我們知道了系統完成一次IO所需要的時間的話我們就能推算出系統IOPS來。

現在我們就來推算一下磁盤的IOPS,假設磁盤的轉速(Rotational Speed)15K RPM平均尋道時間爲5ms最大傳輸速率爲40MB/s(這裏將讀寫速度視爲一樣,實際會差別比較大)。

對於磁盤來說一個完整的IO操作是這樣進行的:當控制器對磁盤發出一個IO操作命令的時候,磁盤的驅動臂(ActuatorArm)帶讀寫磁頭(Head)離開着陸區(LandingZone,位於內圈沒有數據的區域),移動到要操作的初始數據塊所在的磁道(Track)的正上方,這個過程被稱爲尋址(Seeking),對應消耗的時間被稱爲尋址時間(SeekTime);但是找到對應磁道還不能馬上讀取數據,這時候磁頭要等到磁盤盤片(Platter)旋轉到初始數據塊所在的扇區(Sector)落在讀寫磁頭正上方的之後才能開始讀取數據,在這個等待盤片旋轉到可操作扇區的過程中消耗的時間稱爲旋轉延時(RotationalDelay);接下來就隨着盤片的旋轉,磁頭不斷的讀/寫相應的數據塊,直到完成這次IO所需要操作的全部數據,這個過程稱爲數據傳送(DataTransfer),對應的時間稱爲傳送時間(TransferTime)。完成這三個步驟之後一次IO操作也就完成了。

在我們看硬盤廠商的宣傳單的時候我們經常能看到3個參數,分別是平均尋址時間、盤片旋轉速度以及最大傳送速度,這三個參數就可以提供給我們計算上述三個步驟的時間。

第一個尋址時間,考慮到被讀寫的數據可能在磁盤的任意一個磁道,既有可能在磁盤的最內圈(尋址時間最短),也可能在磁盤的最外圈(尋址時間最長),所以在計算中我們只考慮平均尋址時間,也就是磁盤參數中標明的那個平均尋址時間,這裏就採用當前最多的10krmp硬盤的5ms

第二個旋轉延時,和尋址一樣,當磁頭定位到磁道之後有可能正好在要讀寫扇區之上,這時候是不需要額外額延時就可以立刻讀寫到數據,但是最壞的情況確實要磁盤旋轉整整一圈之後磁頭才能讀取到數據,所以這裏我們也考慮的是平均旋轉延時,對於10krpm的磁盤就是(60s/15k)*(1/2)= 2ms

第三個傳送時間,磁盤參數提供我們的最大的傳輸速度,當然要達到這種速度是很有難度的,但是這個速度卻是磁盤純讀寫磁盤的速度,因此只要給定了單次IO的大小,我們就知道磁盤需要花費多少時間在數據傳送上,這個時間就是IOChunk Size / Max Transfer Rate

現在我們就可以得出這樣的計算單次IO時間的公式:

IO Time = Seek Time + 60 sec/Rotational Speed/2 + IO ChunkSize/Transfer Rate

於是我們可以這樣計算出IOPS

IOPS = 1/IO Time = 1/(Seek Time + 60 sec/Rotational Speed/2 + IOChunk Size/Transfer Rate)

對於給定不同的IO大小我們可以得出下面的一系列的數據

4K (1/7.1 ms = 140 IOPS)
    
5ms + (60sec/15000RPM/2) + 4K/40MB = 5 + 2 + 0.1 = 7.1
8k (1/7.2 ms = 139 IOPS)
    
5ms + (60sec/15000RPM/2) + 8K/40MB = 5 + 2 + 0.2 = 7.2
16K (1/7.4 ms = 135 IOPS)
    
5ms + (60sec/15000RPM/2) + 16K/40MB = 5 + 2 + 0.4 = 7.4
32K (1/7.8 ms = 128 IOPS)
    
5ms + (60sec/15000RPM/2) + 32K/40MB = 5 + 2 + 0.8 = 7.8
64K (1/8.6 ms = 116 IOPS)
    
5ms + (60sec/15000RPM/2) + 64K/40MB = 5 + 2 + 1.6 = 8.6

從上面的數據可以看出,當單次IO越小的時候,單次IO所耗費的時間也越少,相應的IOPS也就越大

上面我們的數據都是在一個比較理想的假設下得出來的,這裏的理想的情況就是磁盤要花費平均大小的尋址時間和平均的旋轉延時,這個假設其實是比較符合我們實際情況中的隨機讀寫,在隨機讀寫中,每次IO操作的尋址時間和旋轉延時都不能忽略不計,有了這兩個時間的存在也就限制了IOPS的大小。現在我們考慮一種相對極端的順序讀寫操作,比如說在讀取一個很大的存儲連續分佈在磁盤的文件,因爲文件的存儲的分佈是連續的,磁頭在完成一個讀IO操作之後,不需要從新的尋址,也不需要旋轉延時,在這種情況下我們能到一個很大的IOPS值,如下

4K (1/0.1 ms = 10000 IOPS)
    
0ms + 0ms + 4K/40MB = 0.1
8k (1/0.2 ms = 5000 IOPS)
    
0ms + 0ms + 8K/40MB = 0.2
16K (1/0.4 ms = 2500 IOPS)
    
0ms + 0ms + 16K/40MB = 0.4
32K (1/0.8 ms = 1250 IOPS)
    
0ms + 0ms + 32K/40MB = 0.8
64K (1/1.6 ms = 625 IOPS)
    
0ms + 0ms + 64K/40MB = 1.6

相比第一組數據來說差距是非常的大的,因此當我們要用IOPS來衡量一個IO系統的系能的時候我們一定要說清楚是在什麼情況的IOPS,也就是要說明讀寫的方式以及單次IO的大小,當然在實際當中,特別是在OLTP的系統的,隨機的小IO的讀寫是最有說服力的。

傳輸速度(Transfer Rate)/吞吐率(Throughput)

現在我們要說的傳輸速度(另一個常見的說法是吞吐率)不是磁盤上所表明的最大傳輸速度或者說理想傳輸速度,而是磁盤在實際使用的時候從磁盤系統總線上流過的數據量。有了IOPS數據之後我們是很容易就能計算出對應的傳輸速度來的

Transfer Rate = IOPS * IO Chunk Size

還是那上面的第一組IOPS的數據我們可以得出相應的傳輸速度如下

4K140 * 4K =  560K / 40M = 1.36%
 
8K139 * 8K = 1112K / 40M = 2.71%
16K135 * 16K = 2160K / 40M = 5.27%
32K116 * 32K = 3712K / 40M = 9.06%

可以看出實際上的傳輸速度是很小的,對總線的利用率也是非常的小。

這裏一定要明確一個概念,那就是儘管上面我們使用IOPS來計算傳輸速度,但是實際上傳輸速度和IOPS是沒有直接關係,在沒有緩存的情況下它們共同的決定因素都是對磁盤系統的訪問方式以及單個IO的大小。對磁盤進行隨機訪問時候我們可以利用IOPS來衡量一個磁盤系統的性能,此時的傳輸速度不會太大;但是當對磁盤進行連續訪問時,此時的IOPS已經沒有了參考的價值,這個時候限制實際傳輸速度卻是磁盤的最大傳輸速度。因此在實際的應用當中,只會用IOPS 來衡量小IO的隨機讀寫的性能,而當要衡量大IO連續讀寫的性能的時候就要採用傳輸速度而不能是IOPS了。

IO響應時間(IOResponse Time)

後來關注一下能直接描述IO性能的IO響應時間。IO響應時間也被稱爲IO延時(IOLatency)IO響應時間就是從操作系統內核發出的一個讀或者寫的IO命令到操作系統內核接收到IO迴應的時間,注意不要和單個IO時間混淆了,單IO時間僅僅指的是IO操作在磁盤內部處理的時間,而IO響應時間還要包括IO操作在IO等待隊列中所花費的等待時間。

IO操作在等待隊列裏面消耗的時間有一個衍生於利托氏定理(Little’sLaw)的排隊模型M/M/1模型可以遵循,由於排隊模型算法比較複雜,到現在還沒有搞太明白(如果有誰對M/M/1模型比較精通的話歡迎給予指導),這裏就羅列一下最後的結果,還是那上面計算的IOPS數據來說:

8K IO Chunk Size (135 IOPS7.2 ms)
    
135 => 240.0 ms
    
105 => 29.5 ms
    
75  => 15.7 ms
    
45  => 10.6 ms
 
64K IO Chunk Size(116 IOPS8.6 ms)
    
135 => 沒響應了……
    
105 => 88.6 ms
    
75  => 24.6 ms
    
45  => 14.6 ms

上面的數據可以看出,隨着系統實際IOPS越接近理論的最大值,IO的響應時間會成非線性的增長,越是接近最大值,響應時間就變得越大,而且會比預期超出很多。一般來說在實際的應用中有一個70%的指導值,也就是說在IO讀寫的隊列中,當隊列大小小於最大IOPS70%的時候,IO的響應時間增加會很小,相對來說讓人比較能接受的,一旦超過70%,響應時間就會戲劇性的暴增,所以當一個系統的IO壓力超出最大可承受壓力的70%的時候就是必須要考慮調整或升級了。

另外補充說一下這個70%的指導值也適用於CPU響應時間,這也是在實踐中證明過的,一旦CPU超過70%,系統將會變得受不了的慢。很有意思的東西。

上一篇文章計算中我們可以看到一個15k轉速的磁盤在隨機讀寫訪問的情況下IOPS竟然只有140左右,但在實際應用中我們卻能看到很多標有5000IOPS甚至更高的存儲系統,有這麼大IOPS的存儲系統怎麼來的呢?這就要歸結於各種存儲技術的使用了,在這些存儲技術中使用最廣的就是高速緩存(Cache)和磁盤冗餘陣列(RAID)了,本文就將探討緩存和磁盤陣列提高存儲IO性能的方法。

高速緩存(Cache)

在當下的各種存儲產品中,按照速度從快到慢應該就是內存>閃存>磁盤>磁帶了,然而速度越快也就意味着價格越高,閃存雖然說是發展勢頭很好,但目前來說卻還是因爲價格問題無法普及,因此現在還是一個磁盤作霸王的時代。與CPU和內存速度相比,磁盤的速度無疑是計算機系統中最大的瓶頸了,所以在必須使用磁盤而又想提高性能的情況下,人們想出了在磁盤中嵌入一塊高速的內存用來保存經常訪問的數據從而提高讀寫效率的方法來折中的解決,這塊嵌入的內存就被稱爲高速緩存。

說到緩存,這東西應用現在已經是無處不在,從處於上層的應用,到操作系統層,再到磁盤控制器,還有CPU內部,單個磁盤的內部也都存在緩存,所有這些緩存存在的目的都是相同的,就是提高系統執行的效率。當然在這裏我們只關心跟IO性能相關的緩存,與IO性能直接相關的幾個緩存分別是文件系統緩存(FileSystem Cache)磁盤控制器緩存(DiskController Cache)磁盤緩存(DiskCache,也稱爲DiskBuffer),不過當在計算一個磁盤系統性能的時候文件系統緩存也是不會考慮在內的,因此我們重點考察的就是磁盤控制器緩存和磁盤緩存。

不管是控制器緩存還是磁盤緩存,他們所起的作用主要是分爲三部分:緩存數據、預讀(Read-ahead)和回寫(Write-back)

 

緩存數據

首先是系統讀取過的數據會被緩存在高速緩存中,這樣下次再次需要讀取相同的數據的時候就不用在訪問磁盤,直接從緩存中取數據就可以了。當然使用過的數據也不可能在緩存中永久保留的,緩存的數據一般那是採取LRU算法來進行管理,目的是將長時間不用的數據清除出緩存,那些經常被訪問的卻能一直保留在緩存中,直到緩存被清空。

預讀

預讀是指採用預讀算法在沒有系統的IO請求的時候事先將數據從磁盤中讀入到緩存中,然後在系統發出讀IO請求的時候,就會實現去檢查看看緩存裏面是否存在要讀取的數據,如果存在(即命中)的話就直接將結果返回,這時候的磁盤不再需要尋址、旋轉等待、讀取數據這一序列的操作了,這樣是能節省很多時間的;如果沒有命中則再發出真正的讀取磁盤的命令去取所需要的數據。

 

緩存的命中率跟緩存的大小有很大的關係,理論上是緩存越大的話,所能緩存的數據也就越多,這樣命中率也自然越高,當然緩存不可能太大,畢竟成本在那兒呢。如果一個容量很大的存儲系統配備了一個很小的讀緩存的話,這時候問題會比較大的,因爲小緩存的數據量非常小,相比整個存儲系統來說比例非常低,這樣隨機讀取(數據庫系統的大多數情況)的時候命中率也自然就很低,這樣的緩存不但不能提高效率(因爲絕大部分讀IO都還要讀取磁盤),反而會因爲每次去匹配緩存而浪費時間。

執行讀IO操作是讀取數據存在於緩存中的數量與全部要讀取數據的比值稱爲緩存命中率(ReadCache Hit Radio),假設一個存儲系統在不使用緩存的情況下隨機小IO讀取能達到150IOPS,而它的緩存能提供10%的緩存命中率的話,那麼實際上它的IOPS可以達到150/(1-10%)=166

回寫

首先說一下,用於回寫功能的那部分緩存被稱爲寫緩存(WriteCache)在一套寫緩存打開的存儲中,操作系統所發出的一系列寫IO命令並不會被挨個的執行,這些寫IO的命令會先寫入緩存中,然後再一次性的將緩存中的修改推到磁盤中,這就相當於將那些相同的多個IO合併成一個,多個連續操作的小IO合併成一個大的IO,還有就是將多個隨機的寫IO變成一組連續的寫IO,這樣就能減少磁盤尋址等操作所消耗的時間,大大的提高磁盤寫入的效率。

 

讀緩存雖然對效率提高是很明顯的,但是它所帶來的問題也比較嚴重,因爲緩存和普通內存一樣,掉點以後數據會全部丟失,當操作系統發出的寫IO命令寫入到緩存中後即被認爲是寫入成功,而實際上數據是沒有被真正寫入磁盤的,此時如果掉電,緩存中的數據就會永遠的丟失了,這個對應用來說是災難性的,目前解決這個問題最好的方法就是給緩存配備電池了,保證存儲掉電之後緩存數據能如數保存下來。

和讀一樣,寫緩存也存在一個寫緩存命中率(WriteCache Hit Radio),不過和讀緩存命中情況不一樣的是,儘管緩存命中,也不能將實際的IO操作免掉,只是被合併了而已。

控制器緩存和磁盤緩存除了上面的作用之外還承當着其他的作用,比如磁盤緩存有保存IO命令隊列的功能,單個的磁盤一次只能處理一個IO命令,但卻能接收多個IO命令,這些進入到磁盤而未被處理的命令就保存在緩存中的IO隊列中。

RAID(Redundant Array Of InexpensiveDisks)

如果你是一位數據庫管理員或者經常接觸服務器,那對RAID應該很熟悉了,作爲最廉價的存儲解決方案RAID早已在服務器存儲中得到了普及。在RAID的各個級別中,應當以RAID10RAID5(不過RAID5已經基本走到頭了,RAID6正在崛起中,看看這裏瞭解下原因)應用最廣了。下面將就RAID0RAID1RAID5RAID6RAID10這幾種級別的RAID展開說一下磁盤陣列對於磁盤性能的影響,當然在閱讀下面的內容之前你必須對各個級別的RAID的結構和工作原理要熟悉纔行,這樣纔不至於滿頭霧水,推薦查看wikipedia上面的如下條目:RAIDStandardRAID levelsNested RAID levels

RAID0

RAID0將數據條帶化(striping)將連續的數據分散在多個磁盤上進行存取,系統發出的IO命令(不管讀IO和寫IO都一樣)就可以在磁盤上被並行的執行,每個磁盤單獨執行自己的那一部分請求,這樣的並行的IO操作能大大的增強整個存儲系統的性能。假設一個RAID0陣列有n(n>=2)個磁盤組成,每個磁盤的隨機讀寫的IO能力都達到140的話,那麼整個磁盤陣列的IO能力將是140*n。同時如果在陣列總線的傳輸能力允許的話RAID0的吞吐率也將是單個磁盤的n倍。

RAID1

RAID1在容量上相當於是將兩個磁盤合併成一個磁盤來使用了,互爲鏡像的兩個磁盤裏面保存的數據是完全一樣的,因此在並行讀取的時候速度將是n個磁盤速度的總和,但是寫入就不一樣了,每次寫入都必須同時寫入到兩個磁盤中,因此寫入速度只有n/2

RAID5

我們那一個有n(n>=3)個磁盤的RAID5陣列來看,首先看看RAID5陣列的讀IORAID5是支持並行IO的,而磁盤上的數據呈條帶狀的分佈在所有的磁盤上,因此IO的速度相當於所有磁盤速度的總和。不過這是在沒有磁盤損壞的情況下,當有一個磁盤故障的時候讀取速度也是會下降的,因爲中間需要花時間來計算丟失磁盤上面的數據。

讀取數據的情況相對就要複雜的多了,先來看下RAID5奇偶校驗數據寫入的過程,我們把寫入的數據稱爲D1,當磁盤拿到一個寫IO的命令的時候,它首先會讀取一次要寫入的地址的數據塊中修改之前的數據D0,然後再讀取到當前條帶中的校驗信息P0,接下來就根據D0P0D1這三組數據計算出數據寫入之後的條帶的奇偶校驗信息P1,最後發出兩個寫IO的命令,一個寫入D1,另一個寫入奇偶校驗信息P1。可以看出陣列在實際操作的時候需要讀、讀、寫、寫一共4 IO才能完成一次寫IO操作,也就是實際上的寫入速度只有所有磁盤速度總和的1/4。從這點可以看出RAID5是非常不適合用在要大批量寫入數據的系統上的

RAID6

RAID6RAID5很類似,差別就在於RAID6多了一個用於校驗的磁盤。就讀IO速度上來說這兩個是完全一樣的,都是所有磁盤IO速度的總和。

在寫IO上也很是類似,不同的是RAID將一個命令分成了三次讀、三次寫一共6IO命令才能完成,也就是RAID6實際寫入磁盤的速度是全部磁盤速度之和的1/6。可以看出從寫IORAID6RAID5差別是很大的。

RAID10

RAID0 讀寫速度都很好,卻沒有冗餘保護RAID5RAID6都有同樣的毛病就是寫入的時候慢讀取的時候快。那麼RAID1呢?嗯,這裏要說的就是RAID1,其實不管是RAID10還是RAID01,其實都是組合大於2塊磁盤時候的RAID1當先鏡像後條帶時候就稱爲RAID10先條帶後鏡像的時候稱爲RAID01。從性能上看RAID01RAID10都是一樣的,都是RAID1嘛,但是RAID10在重建故障磁盤的時候性能比RAID01 要快。因爲RAID10其實就是RAID1,所以它的性能與RAID1也就是一樣的了,這裏不需要再做過多的討論。

四個性能指標的變化

IO響應時間(IOResponse Time)

任何時候IO響應時間值得都是單個IO的響應時間,因此,不管磁盤是否組成了磁盤陣列,它的IO響應時間應該都是一樣的。從前面的計算中我們可以看到,如IO響應時間在10ms左右的話是很正常的,但是當IO響應時間比這個值超出太多的時候,你就要開始注意了,很可能就意味着此時你的磁盤系統已經成爲了一個瓶頸。

IOPS

綜合上面兩個部分的討論我們來估算一下陣列下的磁盤總體IOPS,在這裏我們先假設組成陣列的單個磁盤的隨機讀寫的IOPS140,讀寫緩存命中率都爲10%,組成陣列的磁盤個數爲4

因爲不管是那種陣列,磁盤的讀取性能都是所有磁盤之和,所以可以得出下面的讀取IOPS

read IOPS = disk_IOPS/(1-read_cache_hit_ratio)*disk_num =140/(1-10%)*4 = 622

而寫入性能就完全不一樣了,根據上面的討論我們可以得出下面結論:

RAID01 IO request => need 1 actual IO on disk
RAID11 IO request => need 2 actual IO on disk
RAID51 IO request => need 4 actual IO on disk
RAID61 IO request => need 6 actual IO on disk

由此我們也可以計算出寫入IOPS估算公式:

RAID0 write IOPS =disk_IOPS/(1-write_cache_hit_ratio)*disk_num/acture_IO_num =140/(1-10%)*4/1 = 622
RAID1 write IOPS =disk_IOPS/(1-write_cache_hit_ratio)*disk_num/acture_IO_num =140/(1-10%)*4/2 = 311
RAID5 write IOPS =disk_IOPS/(1-write_cache_hit_ratio)*disk_num/acture_IO_num =140/(1-10%)*4/4 = 155
RAID6 write IOPS =disk_IOPS/(1-write_cache_hit_ratio)*disk_num/acture_IO_num =140/(1-10%)*4/6 = 103

實際上從通過上面的計算方法我們還可以估算當給定一個要求的IOPS的情況下,估計下使用各個陣列級別所需要的磁盤的數量。當然我們上面的計算方法只是一個估算,我們忽略很多其他的因素,得出的只是一個大概的數值,不過在實際的應用還是有一定的參考作用的。

本篇最後附送一個計算磁盤系統IOPS的網站――wmarow’s disk & disk array calculator,這個網站提供的計算公式還考慮了諸如陣列條帶大小以及主機方面的因素,很有參考價值,至於怎麼選擇合適的條帶大小,請參考【延伸閱讀】部分。


傳輸速度(Transfer Rate)/吞吐率(Throughput)

實際上估算除了隨機讀寫的IOPS也就知道了隨機讀寫的吞吐率。對於順序讀寫的呢,還是跟前一篇所講的一樣,主要受限於磁盤的限制,不能再拿IOPS來衡量了。

random_throughtput = random_IOPS * IO_chunk_size

dd命令

dd其實是工作於比較低層的一個數據拷貝和轉換的*nix平臺的工具,但是因爲dd命令支持*nix平臺的一些特殊設備,因此我們可以利用dd命令的這個特性來簡單的測試磁盤的性能。

先說一下兩個相關的特殊設備

/dev/null

空設備,通常用作輸出設備,這個是*nix系統上面的黑洞,所有送到這個空設備上的內容都會憑空消失。

/dev/zero

空字符,通常用作輸入,從/dev/zero中讀取時,它能源源不斷的提供空字符(ASCII NUL, 0×00)出來,要多少有多少。

於是就有了下面的用法:

測試磁盤的寫入

/usr/bin/time dd if=/dev/zero of=/tmp/foo bs=4k count=1024000

個命令時往磁盤的文件/tmp/foo中寫入一個4G大小的文件,當然文件的內容全部是空字符了,同時用/usr/bin/time來對命令的執行進行計時,命令中的bs指的是寫入文件時的塊大小,其實就相當於Oracle中的block大小了,count是寫入的塊數。採取這種方法來寫入數據時只是測試的連續讀磁盤的性能,而不是隨機讀的性能,不能採取這種方法檢查一個機器的IOPS的,只能檢查磁盤的吞吐率。

測試磁盤的讀取

/usr/bin/time dd if=/tmp/foo of=/dev/null bs=4k

上面的命令是從/tmp/foo文件中讀取數據,然後扔掉,這裏bs用的是讀取時塊的大小。和上面寫入的命令一樣,這樣測試的僅僅是最大的讀取性能,而不是隨機IO的性能。

還能讀寫同時測試

/usr/bin/time dd if=/tmp/foo of=/tmp/foo2 bs=4k

在上面的命令中都用到了time命令對操作進行計時,這樣才能正確的進行判斷。要記住的一點是dd命令只能夠提供一個大概的測試,通過這個簡單的命令可以對磁盤系統的最大性能有一個大概的瞭解,要了解更詳細的信息還要通過其他方法來查看。


iostat
命令


理解iostat的各項輸出

Linux中,我們執行一個iostat -x命令,我們能看到如下的輸出

$iostat -x
Linux 2.4.21-50a6smp (linux)         11/03/2009

avg-cpu:  %user   %nice    %sys %iowait  %idle
           0.42    0.00   0.26    0.47   98.86

Device:    rrqm/s wrqm/s   r/s   w/s rsec/s  wsec/s    rkB/s    wkB/s avgrq-szavgqu-sz   await  svctm  %util
hdc          0.01   0.00  0.00 0.00    0.07    0.00     0.03    0.00    24.48     0.00    4.90  4.57   0.00
hda          0.89   8.54  0.74 4.49   12.60  104.22     6.30   52.11    22.32     0.03    5.41  1.01   0.53

我們先列舉一下各個性能指標的簡單說明。

rrqm/s

每秒進行merge的讀操作數目。

wrqm/s

每秒進行merge的寫操作數目。

r/s

每秒完成的讀I/O設備次數。

w/s

每秒完成的寫I/O設備次數。

rsec/s

每秒讀扇區數。

wsec/s

每秒寫扇區數。

rkB/s

每秒讀K字節數。

wkB/s

每秒寫K字節數。

avgrq-sz

平均每次設備I/O操作的數據大小(扇區)

avgqu-sz

平均I/O隊列長度。

await

平均每次設備I/O操作的等待時間(毫秒)

svctm

平均每次設備I/O操作的服務時間(毫秒)

%util

一秒中有百分之多少的時間用於I/O操作,或者說一秒中有多少時間I/O隊列是非空的。

要理解這些性能指標我們先看下圖

 

IO的執行過程的各個參數

圖的左邊是iostat顯示的各個性能指標,每個性能指標都會顯示在一條虛線之上,這表明這個性能指標是從虛線之上的那個讀寫階段開始計量的,比如說圖中w/sLinux IO scheduler開始穿過硬盤控制器(CCIS/3ware),這就表明w/s統計的是每秒鐘從Linux IO scheduler通過硬盤控制器的寫IO的數量。

合上圖對讀IO操作的過程做一個說明,在從OS Buffer Cache傳入到OS Kernel(Linux IO scheduler)的讀IO操作的個數實際上是rrqm/s+r/s,直到讀IO請求到達OS Kernel層之後,有每秒鐘有rrqm/s個讀IO操作被合併,最終轉送給磁盤控制器的每秒鐘讀IO的個數爲r/w;在進入到操作系統的設備層 (/dev/sda)之後,計數器開始對IO操作進行計時,最終的計算結果表現是await,這個值就是我們要的IO響應時間了;svctm是在IO操作進入到磁盤控制器之後直到磁盤控制器返回結果所花費的時間,這是一個實際IO操作所花的時間,awaitsvctm相差很大的時候,我們就要注意磁盤的IO性能了;而avgrq-sz是從OS Kernel往下傳遞請求時單個IO的大小,avgqu-sz則是在OS KernelIO請求隊列的平均大小。

現在我們可以將iostat輸出結果和我們前面討論的指標掛鉤了。

平均單次IO大小(IO Chunk Size) <=>avgrq-sz

平均IO響應時間(IO Response Time) <=>await

IOPS(IO per Second) <=> r/s + w/s

吞吐率(Throughtput)<=> rkB/s + wkB/s


iostat
的應用實例

觀察IOSchedulerIO合併(IOMerge)

前面說過IO在執行過程中會被合併以提高效率,下面就結合dd命令和iostat命令看一下。

我們先執行dd命令,設置bs參數值爲1k,完整命令如下

ddif=/dev/zero of=test bs=1k count=1024000

同時打開另外一個終端執行iostat命令,這裏只查看變化那個磁盤的更改,每秒刷新一次數據,完整命令如下

iostat-x hdc7 1

然後我們可以得到下面的結果

Device:   rrqm/s wrqm/s   r/s   w/s  rsec/s wsec/s    rkB/s    wkB/s avgrq-sz avgqu-sz  await  svctm  %util
hdc7         0.00 9447.00  0.00 776.00   0.00 80616.00     0.00 40308.00   103.89  480.18  805.95   1.29 100.00

avg-cpu:  %user   %nice    %sys %iowait  %idle
           0.50    0.00  56.00   43.50    0.00

Device:    rrqm/s wrqm/s   r/s   w/s rsec/s  wsec/s    rkB/s    wkB/s avgrq-szavgqu-sz   await  svctm  %util
hdc7         0.00 9534.00  0.00 872.00   0.00 81384.00     0.00 40692.00    93.33  274.56  401.19   1.14  99.00

avg-cpu:  %user   %nice    %sys %iowait  %idle
           2.50    0.00  46.50   14.00   37.00

Device:    rrqm/s wrqm/s   r/s   w/s rsec/s  wsec/s    rkB/s    wkB/s avgrq-sz avgqu-sz  await  svctm  %util
hdc7         0.00 6766.00  1.00 276.00   8.00 58808.00     4.00 29404.00   212.33  197.27  321.66   1.95  54.00

avg-cpu:  %user   %nice    %sys %iowait  %idle
           0.50    0.00   0.50    0.00   99.00

結果中第一組數據中的avgrq-sz,爲103.89個扇區,磁盤的每個扇區爲512字節,因此平均IO大小爲103.89*512/1024=52k字節,遠遠大於我們dd命令時給定的參數1k字節,也就是說IO在中間被合併了。看巨大的wrqm/s也能得出同樣的結論。

附:在Windows中監視IO性能

本來準備寫一篇windows中監視IO性能的,後來發現好像可寫的內容不多,windows在細節這方面做的不是那麼的好,不過那些基本信息還是有的。

Windows中監視性能基本都用性能監視器了,與IO性能相關的有兩個大類,一個是”LogicalDisk”,另外一個”PhysicalDisk””LogicalDisk”更多的是用來監視文件相關的IO性能,而”PhysicalDisk”則是用來監視LUN者是磁盤卷,下面就列舉下與前面所列舉的IO性能相關的計數器,具體的自己研究了:

單次IO大小

Avg.Disk Bytes/Read

Avg.Disk Bytes/Write

IO響應時間

Avg.Disk sec/Read

Avg.Disk sec/Write

IOPS

DiskReads/sec

DiskWrites/sec

DiskTransfers/sec

IO吞吐率

DiskBytes/sec

DiskRead Bytes/sec

DiskWrite Bytes/sec

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章