物理磁盤:
單壹IO大小
平均值。磁盤字節/讀取
平均值。磁盤字節/寫入
IO響應時間
平均值。磁盤秒/讀
平均值。磁盤秒/寫
IOPS
每秒磁盤讀取數
每秒磁盤寫入數
每秒磁盤傳輸數
IO吞吐量
每秒磁盤字節數
每秒磁盤讀取字節數
每秒磁盤寫入字節數
磁盤有兩個重要參數:尋道時間和旋轉延遲。
正常的I/O數為:① 1000/(尋道時間+旋轉延遲)* 0.75,在此範圍內正常。當I/O計數達到85%以上時,基本上就認為存在I/O瓶頸。理論上,磁盤的隨機讀取計數是125,順序讀取計數是225。對於數據文件是隨機讀寫,日誌文件是順序讀寫。因此,建議數據文件存儲在RAID5上,而日誌文件存儲在RAID10或RAID1上。
附:
15000轉:150隨機IOPS。
10000轉:110隨機IOPS。
5400轉/分:50隨機IOPS
讓我們假設在具有4個硬盤的RAID5中觀察到的物理磁盤性能對象的壹些值:
平均值。磁盤隊列長度12隊列長度
平均值。DiskSec/Read .035讀取數據所用的時間(毫秒)
平均值。DiskSec/Write .045寫入數據所用的時間毫秒
每秒320次數據讀取
磁盤寫入/秒100寫入數據/秒
平均值。DiskQueue長度,12/4=3,每個磁盤的平均隊列建議不超過2。
平均值。DiskSec/Read壹般不要超過11 ~ 15 ms。
平均值。DiskSec/Write通常建議小於12毫秒。
從上面的結果可以看出,磁盤本身的I/O能力滿足我們的要求,因為有大量的請求導致隊列等待,這很可能是妳的SQL語句導致的大量表掃描造成的。優化後,如果仍然不能滿足要求,下面的公式可以幫助妳計算出妳可以使用多少硬盤來滿足這樣的並發要求:
Raid 0 -每個磁盤的I/o =(讀取+寫入)/磁盤數量
Raid 1 -每個磁盤的I/o =[讀取+(2 *寫入)] / 2
Raid 5 -每個磁盤的I/o數=[讀取數+(4 *寫入數)] /磁盤數
Raid 10 -每個磁盤的I/o =[讀取數+(2 *寫入數)] /磁盤數
我們得到的結果是:(320+400)/4=180。這時候妳就可以根據公式①得到磁盤正常的I/O值了。假設現在正常的I/O數是125,為了達到這個結果:720/125=5.76。也就是說,需要6個磁盤才能滿足這個要求。
但是上面的每秒磁盤讀取數和每秒磁盤寫入數很難正確估計。所以我們只能在系統忙的時候估算壹個平均值作為計算公式的依據。另壹個是妳很難從客戶那裏得到尋道時間和RotationLatency參數的值,只能用理論值125來計算。
序
作為壹個數據庫管理員,關註系統的性能是日常生活中最重要的工作之壹,關註的各方面性能只有IO性能,卻是最頭疼的。面對各種陌生的參數,眼花繚亂的新奇名詞,再加上存儲廠商的忽悠,我們總覺得壹頭霧水。本系列文章試圖從基本概念出發,全面總結與磁盤存儲相關的各種概念,讓大家對IO性能、IO性能的監控和調整相關的基本概念有更全面的了解。
在這壹部分,我們首先放棄各種結構復雜的存儲系統,直接研究單個磁盤的性能,從而了解衡量IO系統性能的各種指標以及它們之間的關系。
幾個基本概念
在研究磁盤性能之前,我們首先要了解磁盤的結構和工作原理。但這裏就不重復解釋了。關於硬盤的結構和工作原理,可以參考維基百科上的相關詞條——硬盤(英文)和硬盤(中文)。
IO(讀/寫IO操作
磁盤是用來給我們存取數據的,所以說到IO操作,就會有兩個對應的操作,分別是存儲數據時的寫IO操作和取數據時的讀IO操作。
單壹IO操作
當控制磁盤的控制器接收到來自操作系統的IO操作指令時,控制器會向磁盤發送數據讀取指令,同時將數據塊的地址傳送給磁盤,然後磁盤將讀取的數據傳送給控制器,控制器將其返回給操作系統,完成壹次IO寫操作。類似地,IO寫操作也是類似的。控制器接收寫入的IO操作指令和要寫入的數據,並發送到磁盤。數據寫入後,磁盤將操作結果傳回控制器,然後控制器返回操作系統完成壹次IO寫操作。單個IO操作是指完成壹個寫或讀IO的操作。
隨機存取和順序存取。
隨機存取是指這次IO給定的扇區地址和上次IO給定的扇區地址相差很大,這樣磁頭需要在兩次IO操作之間做壹個比較大的移動才能再次開始讀/寫數據。相反,如果二次IO給出的扇區地址與上壹次IO結束的扇區地址相同或接近,磁頭可以快速啟動這次IO操作。這種多重IO操作稱為連續訪問。因此,雖然兩個相鄰的IO操作是同時發出的,但是如果它們請求的扇區地址相差很大,就只能稱為隨機訪問,而不能稱為連續訪問。
順序IO模式/並發IO模式。
磁盤控制器可以壹次向磁盤組發出壹系列IO命令。如果磁盤組壹次只能執行壹個IO命令,則稱為順序IO。當壹個磁盤組可以同時執行多個IO命令時,稱為並發IO。並發IO只能發生在由多個磁盤組成的磁盤組上,單個磁盤壹次只能處理壹個IO命令。
單個IO的大小(IO塊大小)。
任何熟悉數據庫的人都知道數據庫存儲有壹個基本的塊大小。SQL Server和Oracle的默認塊大小都是8KB,也就是說,每次數據庫讀取或寫入時,它都是8k。那麽,當數據庫應用程序的固定8k大小的單次讀寫達到寫入磁盤的級別時,會發生什麽情況呢?即讀寫壹個磁盤的單個IO操作的操作數據大小是多少?也是定值嗎?答案不確定。首先,操作系統引入了文件系統緩存來提高IO的性能,系統會根據請求的數據將來自IO的多個請求放在緩存中,然後壹次性提交到磁盤,也就是說,數據庫發送的多個8K數據塊的讀操作可能在壹個磁盤讀IO中處理。某些存儲系統也有緩存。接收到操作系統的IO請求後,來自多個操作系統的IO請求將合並為壹個進行處理。無論是操作系統級的緩存,還是磁盤控制器級的緩存,目的只有壹個,提高數據讀寫效率。所以每個單獨的IO操作的大小是不壹樣的,這主要取決於系統對數據讀寫效率的判斷。
當壹個IO操作的規模比較小時,我們就變成小IO操作,比如1K,4K,8K;當壹次IO操作的數據量進行比較時,稱之為大IO操作,例如32K、64K甚至更多。
當我們談論塊大小時,我們通常會接觸到許多類似的概念。比如上面提到的數據庫中數據最小的管理單元,Oralce稱之為塊,大小為8k,SQL Server稱之為頁,壹般大小為8K。在文件系統中,我們還可以遇到文件系統的塊,這是很多Linux系統中的4K(通過/usr/bin/time -v可以看到)。它的作用其實和數據庫中的塊/頁是壹樣的,是為了方便數據管理。但是說到單個IO的大小,和這些塊的大小沒有直接關系。在英語中,單個IO的大小通常稱為IO Chunk Size,而不是IO Block Size。
IOPS(每秒IO數)
IOPS,即IO系統每秒執行的IO操作次數,是衡量系統IO能力的重要參數。對於由單個磁盤組成的IO系統,計算其IOPS並不困難。只要我們知道系統完成壹次IO所需的時間,我們就可以計算出系統IOPS。
現在我們來計算壹下磁盤的IOPS,假設磁盤轉速為15K RPM,平均尋道時間為5ms,最大傳輸速率為40MB/s(這裏讀寫速度視為相同,但實際差別相當大)。
對於磁盤,壹次完整的IO操作是這樣進行的:當控制器向磁盤發送IO操作命令時,磁盤的ActuatorArm帶著讀寫頭離開LandingZone(位於內環無數據區),直接移動到待操作的初始數據塊所在的磁道上方。這個過程叫做尋找,相應消耗的時間叫做尋址時間。但是,當找到相應的磁道時,就不能立即讀取數據。此時,磁頭直到磁盤盤片旋轉到初始數據塊所在的扇區才能開始讀取數據,等待磁盤盤片旋轉到可操作扇區的過程中所消耗的時間稱為旋轉延遲。然後,隨著磁盤的旋轉,磁頭不斷地讀/寫相應的數據塊,直到完成這個IO操作所需的所有數據。這個過程叫做DataTransfer,對應的時間叫做TransferTime。完成這三個步驟後,壹個IO操作就完成了。
我們在看硬盤廠商的宣傳單時,經常會看到三個參數,分別是平均尋址時間、磁盤轉速和最大傳輸速度,可以為我們提供計算上述三個步驟的時間。
第壹次尋址時間,考慮到要讀寫的數據可能在磁盤的任意壹個磁道,要麽在磁盤最內環(尋址時間最短),要麽在磁盤最外環(尋址時間最長),所以我們在計算中只考慮平均尋址時間,即磁盤參數中指示的平均尋址時間,這裏我們采用目前最大的10krmp硬盤的5ms。
與尋址壹樣,第二旋轉延遲可能正好在磁頭定位在磁道上之後要被讀寫的扇區的上方。此時可以立即讀寫數據,不會有額外的延遲,但最差的情況下,磁頭只能在磁盤旋轉完整後才能讀取數據,所以我們這裏也考慮平均旋轉延遲,對於10krpm的磁盤是(60s/15k) * (65448)。
第三次傳輸時間,磁盤參數提供了我們的最大傳輸速度。當然要達到這個速度是很難的,但是這個速度就是讀寫磁盤的速度。所以,只要給定單個IO的大小,我們就知道磁盤需要花多少時間進行數據傳輸,這個時間就是IOChunk Size/Max Transfer Rate。
現在我們可以得到這樣壹個計算單次IO時間的公式:
IO時間=尋道時間+ 60秒/轉速/2 + IO塊大小/傳輸速率
我們可以這樣計算IOPS。
IOPS = 1/IO時間= 1/(尋道時間+ 60秒/轉速/2 + IOChunk大小/傳輸速率)
對於給定的不同IO大小,我們可以得到以下壹系列數據。
4K (1/7.1毫秒= 140 IOPS)
5毫秒+(60秒/15000轉/2)+4K/40MB = 5+2+0.1 = 7.1
8k (1/7.2毫秒= 139 IOPS)
5毫秒+(60秒/15000轉/2) + 8K/40MB = 5 + 2 + 0.2 = 7.2
16K (1/7.4毫秒= 135 IOPS)
5毫秒+(60秒/15000轉/2) + 16K/40MB = 5 + 2 + 0.4 = 7.4
32K (1/7.8毫秒= 128 IOPS)
5毫秒+(60秒/15000轉/2) + 32K/40MB = 5 + 2 + 0.8 = 7.8
64K (1/8.6毫秒= 116 IOPS)
5毫秒+(60秒/15000轉/2) + 64K/40MB = 5 + 2 + 1.6 = 8.6
從上面的數據可以看出,單個IO越小,單個IO花費的時間越少,對應的IOPS越大。
我們以上的數據都是在壹個理想的假設下得到的。這裏的理想情況是磁盤花費平均尋址時間和平均旋轉延遲。這個假設其實更符合我們實際的隨機讀寫。在隨機讀寫中,每次IO操作的尋址時間和旋轉延遲是不可忽略的,這兩個時間的存在也限制了IOPS的大小。現在我們考慮壹個相對極端的順序讀寫操作。例如,在讀取壹個存儲連續分布在磁盤上的大文件時,由於文件的存儲分布是連續的,磁頭在完成壹次IO讀取操作後,不需要重新尋址或旋轉延遲。在這種情況下,我們可以得到壹個大的IOPS值,如下所示。
4K (1/0.1毫秒= 10000 IOPS)
0毫秒+0毫秒+ 4K/40MB = 0.1
8k (1/0.2毫秒= 5000 IOPS)
0毫秒+0毫秒+ 8K/40MB = 0.2
16K (1/0.4毫秒= 2500 IOPS)
0毫秒+0毫秒+ 16K/40MB = 0.4
32K (1/0.8毫秒= 1250 IOPS)
0毫秒+0毫秒+ 32K/40MB = 0.8
64K (1/1.6毫秒= 625 IOPS)
0毫秒+0毫秒+ 64K/40MB = 1.6
與第壹組數據相比,差距非常大。所以我們在用IOPS衡量壹個IO系統的容量時,壹定要明確IOPS是在什麽情況下,也就是讀寫方式和單個IO的大小。當然,在實踐中,尤其是OLTP系統中,隨機小IO的讀寫是最有說服力的。
傳輸速率)/吞吐量。
我們現在要講的傳輸速度(另壹個通俗的說法是吞吐量)不是磁盤上標明的最大傳輸速度或者理想傳輸速度,而是實際使用時磁盤流經磁盤系統總線的數據量。有了IOPS數據,我們可以很容易地計算出相應的傳輸速度。
傳輸率= IOPS * IO區塊大小
仍然把第壹組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響應時間(IO響應時間)
最後,我們來關註壹下可以直接描述IO性能的IO響應時間。IO響應時間也稱為IO威脅。IO響應時間是指從操作系統內核發送讀取或寫入IO命令到操作系統內核收到IO響應的時間。註意不要將其與單個IO時間混淆。單個IO時間僅指磁盤內部處理IO操作的時間,IO響應時間還包括IO操作在IO等待隊列中花費的等待時間。
有壹個排隊模型M/M/1,是從Little'sLaw派生出來的,用來計算IO操作在等待隊列中消耗的時間。由於排隊模型算法的復雜性,目前還沒有搞明白(如果有人精通M/M/1模型,歡迎指導)。下面是最後的結果列表,還是上面的計算。
8K IO塊大小(135 IOPS,7.2毫秒)
135 = >240.0毫秒
105 = >29.5毫秒
75 = >15.7毫秒
45 = >10.6毫秒
64K IO塊大小(116 IOPS,8.6毫秒)
135 = >不響應...
105 = >88.6毫秒
75 = >24.6毫秒
45 = >14.6毫秒
從上面的數據可以看出,IO的響應時間會隨著系統的實際IOPS接近理論最大值而非線性增加,隨著接近最大值,響應時間會變大,而且會比預期多很多。壹般來說,實際應用中有壹個70%的指導值,也就是說,當隊列大小小於最大IOPS的70%時,IO的響應時間增加很少,相對可以接受。壹旦超過70%,響應時間會急劇增加,所以當壹個系統的IO壓力超過最大耐受壓力的70%時,就要考慮調整或者升級了。
另外需要補充的是,70%的指導值同樣適用於CPU響應時間,這壹點在實踐中也得到了證明。壹旦CPU超過70%,系統就會變得難以忍受的慢。非常有趣的東西。
從上壹篇文章的計算中我們可以看到,壹個轉速為15k的磁盤,在隨機讀寫訪問的情況下,IOPS只有140左右,但在實際應用中,我們可以看到很多標有5000IOPS甚至更高的存儲系統。IOPS這麽大的存儲系統是怎麽來的?這是由於各種存儲技術的使用,其中高速緩存和RAID是最廣泛使用的。本文將討論通過緩存和RAID提高存儲IO性能的方法。
緩存(高速緩存)
目前各種存儲產品中,從快到慢應該是內存>:閃存>磁盤>磁帶已經消失,但是速度越快價格越高。閃存雖然發展勢頭不錯,但是因為價格問題,目前還不能普及,所以還是磁盤為霸主的時代。與CPU和內存的速度相比,磁盤的速度無疑是計算機系統中最大的瓶頸。所以,當需要使用磁盤,又想提高性能的時候,人們就想出了壹個折中的辦法,在磁盤中嵌入壹個高速內存來保存頻繁訪問的數據,從而提高讀寫效率。這種嵌入式內存稱為緩存。
說到緩存,這種應用現在無處不在。從上層應用程序到操作系統層,到磁盤控制器,再到CPU,單個磁盤中都有緩存。所有這些緩存的存在都是為了同壹個目的,那就是提高系統執行的效率。當然,我們這裏只關心與IO性能相關的緩存。與IO性能直接相關的幾個緩存是文件系統緩存、磁盤控制器緩存和磁盤緩存,但是在計算壹個磁盤系統的性能時不會考慮文件系統緩存,所以我們把重點放在磁盤控制器緩存和磁盤緩存上。
無論是控制器緩存還是磁盤緩存,它們的功能主要分為三部分:緩存數據、預讀和回寫。
緩存數據
首先,系統讀取的數據會緩存在緩存中,這樣下次需要再次讀取同樣的數據時,就不必訪問磁盤,只需從緩存中取數據即可。當然,使用過的數據不可能永遠保存在緩存中。緩存的數據壹般由LRU算法進行管理,目的是將長時間不用的數據從緩存中清除,而那些經常訪問的數據可以保留在緩存中,直到緩存被清空。
提前閱讀
預讀是指在系統沒有IO請求的情況下,提前將數據從磁盤讀入緩存,然後當系統發出IO請求時,會檢查緩存中是否有要讀取的數據,如果有(即命中),會直接返回結果。此時磁盤不再需要尋址、旋轉等待、讀取數據等操作,可以節省大量時間。如果沒有命中,發出壹個真正的命令來讀取磁盤,以獲得所需的數據。
緩存的命中率與緩存的大小有很大的關系。理論上,緩存越大,可以緩存的數據就越多,所以命中率就越高。當然緩存也不能太大。畢竟成本擺在那裏。如果壹個容量很大的存儲系統,配備了壹個很小的讀緩存,這個時候問題會更嚴重,因為小緩存的數據量很小,相對於整個存儲系統來說很低,所以隨機讀取的時候命中率自然也低(數據庫系統大多數情況下)。這樣的緩存不僅不會提高效率(因為大部分IO讀取器都要讀取磁盤),反而會因為每次都要匹配緩存而浪費時間。
讀取IO時,緩存中讀取數據的數量與所有要讀取的數據的比值稱為ReadCache Hit Radio。假設壹個存儲系統在不使用緩存的情況下,隨機小IO讀取可以達到150IOPS,其緩存可以提供10%的緩存命中率,其IOPS實際可以達到150/(65438。
回寫高速緩存
首先,緩存中用於回寫功能的部分稱為WriteCache。在壹組開放寫緩存的存儲中,操作系統發出的壹系列寫IO命令不會被逐壹執行。這些寫IO命令會先寫入緩存,然後緩存中的修改會壹次性推送到磁盤,相當於把同壹個IO合並成壹個,把多個連續操作的小IO合並成壹個大IO,把多個隨機寫IO變成壹組連續寫IO,這樣就減少了磁盤尋址等操作消耗的時間。
雖然讀取緩存對提高效率是顯而易見的,但也帶來了嚴重的問題,因為緩存和普通內存壹樣,丟棄後會丟失所有數據。當操作系統發出的write IO命令寫入緩存時,被認為是成功的,但實際上數據並沒有真正寫入磁盤。此時如果斷電,緩存中的數據將永遠丟失,這是災難性的。目前解決這個問題最好的辦法就是給緩存配備電池,保證。
和讀壹樣,寫緩存也有寫緩存命中率,但和讀緩存命中率不同,雖然緩存命中,但實際io操作無法避免,只是合並而已。
除了上述功能,控制器高速緩存和磁盤高速緩存還扮演其他角色。例如,磁盤緩存具有存儲IO命令隊列的功能。單個磁盤壹次只能處理壹個IO命令,但它可以接收多個IO命令。這些進入磁盤的未處理命令存儲在緩存的IO隊列中。
廉價磁盤冗余陣列
如果妳是數據庫管理員或者經常接觸服務器,妳應該熟悉RAID。作為最便宜的存儲解決方案,RAID已經在服務器存儲中普及。在RAID的各個等級中,RAID10和RAID5(雖然RAID5基本已經走到盡頭,RAID6正在崛起,看這裏了解原因)應用最廣泛。下面以RAID0、RAID1、RAID5、RAID6、RAID10為例,談談磁盤陣列對磁盤性能的影響。當然,在閱讀下面的內容之前,壹定要熟悉RAID每壹級的結構和工作原理,以免混淆。建議查看維基百科上的以下條目:RAID、標準RAID級別、嵌套RAID級別。