轉自:http://m635674608.iteye.com/blog/1935899
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操作,比如說1K,4K,8K這樣的;當一次IO操作的資料量比較的的時候稱為大IO操作,比如說32K,64K甚至更大。
在我們說到塊大小(Block Size)的時候通常我們會接觸到多個類似的概念,像我們上面提到的那個在資料庫裡面的資料最小的管理機關,Oralce稱之為塊(Block),大小一般為8K,SQL Server稱之為頁(Page),一般大小也為8k。在檔案系統裡面我們也能碰到一個檔案系統的塊,在現在很多的Linux系統中都是4K(通過/usr/bin/time -v可以看到),它的作用其實跟資料庫裡面的塊/頁是一樣的,都是為了友善資料的管理。但是說到單次IO的大小,跟這些塊的大小都是沒有直接關系的,在英文裡單次IO大小通常被稱為是IO Chunk Size,不會說成是IO Block Size的。
IOPS(IO per Second)
IOPS,IO系統每秒所執行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時間的公式:
IOTime = SeekTime + 60sec/RotationalSpeed/2 + IOChunkSize/TransferRate
于是我們可以這樣計算出IOPS
IOPS = 1/IOTime = 1/(SeekTime + 60sec/RotationalSpeed/2 + IOChunkSize/TransferRate)
對于給定不同的IO大小我們可以得出下面的一系列的資料
4K(1/7.1ms = 140IOPS)
5ms + (60sec/15000RPM/2) + 4K/40MB = 5 + 2 + 0.1 = 7.1
8k(1/7.2ms = 139IOPS)
5ms + (60sec/15000RPM/2) + 8K/40MB = 5 + 2 + 0.2 = 7.2
16K(1/7.4ms = 135IOPS)
5ms + (60sec/15000RPM/2) + 16K/40MB = 5 + 2 + 0.4 = 7.4
32K(1/7.8ms = 128IOPS)
5ms + (60sec/15000RPM/2) + 32K/40MB = 5 + 2 + 0.8 = 7.8
64K(1/8.6ms = 116IOPS)
5ms + (60sec/15000RPM/2) + 64K/40MB = 5 + 2 + 1.6 = 8.6
從上面的資料可以看出,當單次IO越小的時候,單次IO所耗費的時間也越少,相應的IOPS也就越大。
上面我們的資料都是在一個比較理想的假設下得出來的,這裡的理想的情況就是磁盤要花費平均大小的尋址時間和平均的旋轉延時,這個假設其實是比較符合我們實際情況中的随機讀寫,在随機讀寫中,每次IO操作的尋址時間和旋轉延時都不能忽略不計,有了這兩個時間的存在也就限制了IOPS的大小。現在我們考慮一種相對極端的順序讀寫操作,比如說在讀取一個很大的存儲連續分布在磁盤的檔案,因為檔案的存儲的分布是連續的,磁頭在完成一個讀IO操作之後,不需要從新的尋址,也不需要旋轉延時,在這種情況下我們能到一個很大的IOPS值,如下
4K(1/0.1ms = 10000IOPS)
0ms + 0ms + 4K/40MB = 0.1
8k(1/0.2ms = 5000IOPS)
0ms + 0ms + 8K/40MB = 0.2
16K(1/0.4ms = 2500IOPS)
0ms + 0ms + 16K/40MB = 0.4
32K(1/0.8ms = 1250IOPS)
0ms + 0ms + 32K/40MB = 0.8
64K(1/1.6ms = 625IOPS)
0ms + 0ms + 64K/40MB = 1.6
相比第一組資料來說差距是非常的大的,是以當我們要用IOPS來衡量一個IO系統的系能的時候我們一定要說清楚是在什麼情況的IOPS,也就是要說明讀寫的方式以及單次IO的大小,當然在實際當中,特别是在OLTP的系統的,随機的小IO的讀寫是最有說服力的。
傳輸速度(Transfer Rate)/吞吐率(Throughput)
現在我們要說的傳輸速度(另一個常見的說法是吞吐率)不是磁盤上所表明的最大傳輸速度或者說理想傳輸速度,而是磁盤在實際使用的時候從磁盤系統總線上流過的資料量。有了IOPS資料之後我們是很容易就能計算出對應的傳輸速度來的
TransferRate = IOPS * IOChunkSize
還是那上面的第一組IOPS的資料我們可以得出相應的傳輸速度如下
4K: 140 * 4K = 560K / 40M = 1.36%
8K: 139 * 8K = 1112K / 40M = 2.71%
16K: 135 * 16K = 2160K / 40M = 5.27%
32K: 116 * 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資料來說:
8KIOChunkSize(135IOPS, 7.2ms)
135 => 240.0ms
105 => 29.5ms
75 => 15.7ms
45 => 10.6ms
64KIOChunkSize(116IOPS, 8.6ms)
135 => 沒響應了……
105 => 88.6ms
75 => 24.6ms
45 => 14.6ms
從上面的資料可以看出,随着系統實際IOPS越接近理論的最大值,IO的響應時間會成非線性的增長,越是接近最大值,響應時間就變得越大,而且會比預期超出很多。一般來說在實際的應用中有一個70%的指導值,也就是說在IO讀寫的隊列中,當隊列大小小于最大IOPS的70%的時候,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的各個級别中,應當以RAID10和RAID5(不過RAID5已經基本走到頭了,RAID6正在崛起中,看看這裡了解下原因)應用最廣了。下面将就RAID0,RAID1,RAID5,RAID6,RAID10這幾種級别的RAID展開說一下磁盤陣列對于磁盤性能的影響,當然在閱讀下面的内容之前你必須對各個級别的RAID的結構和工作原理要熟悉才行,這樣才不至于滿頭霧水,推薦檢視wikipedia上面的如下條目:RAID,StandardRAID levels,Nested 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陣列的讀IO,RAID5是支援并行IO的,而磁盤上的資料呈條帶狀的分布在所有的磁盤上,是以讀IO的速度相當于所有磁盤速度的總和。不過這是在沒有磁盤損壞的情況下,當有一個磁盤故障的時候讀取速度也是會下降的,因為中間需要花時間來計算丢失磁盤上面的資料。
讀取資料的情況相對就要複雜的多了,先來看下RAID5奇偶校驗資料寫入的過程,我們把寫入的資料稱為D1,當磁盤拿到一個寫IO的指令的時候,它首先會讀取一次要寫入的位址的資料塊中修改之前的資料D0,然後再讀取到目前條帶中的校驗資訊P0,接下來就根據D0,P0,D1這三組資料計算出資料寫入之後的條帶的奇偶校驗資訊P1,最後發出兩個寫IO的指令,一個寫入D1,另一個寫入奇偶校驗資訊P1。可以看出陣列在實際操作的時候需要讀、讀、寫、寫一共4個IO才能完成一次寫IO操作,也就是實際上的寫入速度隻有所有磁盤速度總和的1/4。從這點可以看出RAID5是非常不适合用在要大批量寫入資料的系統上的。
RAID6
RAID6和RAID5很類似,差别就在于RAID6多了一個用于校驗的磁盤。就讀IO速度上來說這兩個是完全一樣的,都是所有磁盤IO速度的總和。
在寫IO上也很是類似,不同的是RAID将一個指令分成了三次讀、三次寫一共6次IO指令才能完成,也就是RAID6實際寫入磁盤的速度是全部磁盤速度之和的1/6。可以看出從寫IO看RAID6比RAID5差别是很大的。
RAID10
RAID0 讀寫速度都很好,卻沒有備援保護;RAID5和RAID6都有同樣的毛病就是寫入的時候慢,讀取的時候快。那麼RAID1呢?嗯,這裡要說的就是RAID1,其實不管是RAID10還是RAID01,其實都是組合大于2塊磁盤時候的RAID1,當先鏡像後條帶時候就稱為RAID10,先條帶後鏡像的時候稱為RAID01。從性能上看RAID01和RAID10都是一樣的,都是RAID1嘛,但是RAID10在重建故障磁盤的時候性能比RAID01要快。因為RAID10其實就是RAID1,是以它的性能與RAID1也就是一樣的了,這裡不需要再做過多的讨論。
四個性能名額的變化
在任何時候IO響應時間值得都是單個IO的響應時間,是以,不管磁盤是否組成了磁盤陣列,它的IO響應時間應該都是一樣的。從前面的計算中我們可以看到,如果IO響應時間在10ms左右的話是很正常的,但是當IO響應時間比這個值超出太多的時候,你就要開始注意了,很可能就意味着此時你的磁盤系統已經成為了一個瓶頸。
IOPS
綜合上面兩個部分的讨論我們來估算一下陣列下的磁盤總體IOPS,在這裡我們先假設組成陣列的單個磁盤的随機讀寫的IOPS為140,讀寫緩存命中率都為10%,組成陣列的磁盤個數為4。
因為不管是那種陣列,磁盤的讀取性能都是所有磁盤之和,是以可以得出下面的讀取IOPS:
readIOPS = disk_IOPS/(1-read_cache_hit_ratio)*disk_num =140/(1-10%)*4 = 622
而寫入性能就完全不一樣了,根據上面的讨論我們可以得出下面結論:
RAID0: 1IOrequest => need1actualIOondisk
RAID1: 1IOrequest => need2actualIOondisk
RAID5: 1IOrequest => need4actualIOondisk
RAID6: 1IOrequest => need6actualIOondisk
由此我們也可以計算出寫入IOPS估算公式:
RAID0writeIOPS =disk_IOPS/(1-write_cache_hit_ratio)*disk_num/acture_IO_num =140/(1-10%)*4/1 = 622
RAID1writeIOPS =disk_IOPS/(1-write_cache_hit_ratio)*disk_num/acture_IO_num =140/(1-10%)*4/2 = 311
RAID5writeIOPS =disk_IOPS/(1-write_cache_hit_ratio)*disk_num/acture_IO_num =140/(1-10%)*4/4 = 155
RAID6writeIOPS =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,這個網站提供的計算公式還考慮了諸如陣列條帶大小以及主機方面的因素,很有參考價值,至于怎麼選擇合适的條帶大小,請參考【延伸閱讀】部分。
實際上估算除了随機讀寫的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隊列是非空的。
要了解這些性能名額我們先看下圖
上圖的左邊是iostat顯示的各個性能名額,每個性能名額都會顯示在一條虛線之上,這表明這個性能名額是從虛線之上的那個讀寫階段開始計量的,比如說圖中的w/s從Linux 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操作所花的時間,當await與svctm相差很大的時候,我們就要注意磁盤的IO性能了;而avgrq-sz是從OS Kernel往下傳遞請求時單個IO的大小,avgqu-sz則是在OS Kernel中IO請求隊列的平均大小。
現在我們可以将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的應用執行個體
觀察IOScheduler的IO合并(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
0.50 0.00 56.00 43.50 0.00
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
2.50 0.00 46.50 14.00 37.00
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
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
DiskReads/sec
DiskWrites/sec
DiskTransfers/sec
IO吞吐率
DiskBytes/sec
DiskRead Bytes/sec
DiskWrite Bytes/sec