在資料庫最佳化和儲存規劃過程中,總會提到 IO 的一些重要概念,在這裡就詳細記錄一下,對這個概念的熟悉程度也決定了對資料庫與儲存最佳化的理解程度,以下這些概念並非權威檔案,權威程度肯定就不能說了。
讀/寫 IO,最為常見說法,讀 IO,就是發指令,從磁碟讀取某段扇區的內容。指令一般是通知磁碟開始扇區位置,然後給出需要從這個初始扇區往後讀取的連續扇區個數,同時給出動作是讀,還是寫。磁碟收到這條指令,就會按照指令的要求,讀或者寫資料。控制器發出的這種指令+資料,就是一次 IO,讀或者寫。
大/小塊 IO,指控制器的指令中給出的連續讀取扇區數目的多少,如果數目很大,比如 128,64 等等,就應該算是大塊 IO,如果很小,比如 1, 4,8 等等,就應該算是小塊 IO,大塊和小塊之間,沒有明確的界限。
連續/隨機 IO,連續和隨機,是指本次 IO 給出的初始扇區地址,和上一次 IO 的結束扇區地址,是不是完全連續的,或者相隔不多的,如果是,則本次 IO 應該算是一個連續 IO,如果相差太大,則算一次隨機 IO 。連續 IO,因為本次初始扇區和上次結束扇區相隔很近,則磁頭幾乎不用換道或換道時間極短;如果相差太大,則磁頭需要很長的換道時間,如果隨機 IO 很多,導致磁頭不停換道,效率大大降底。
順序/併發 IO,這個的意思是,磁碟控制器每一次對磁碟組發出的指令套(指完成一個事物所需要的指令或者資料),是一條還是多條。如果是一條,則控制器 WordPress 加速快取中的 IO 佇列,只能一個一個的來,此時是順序 IO;如果控制器可以同時對磁碟組中的多塊磁碟,同時發出指令套,則每次就可以執行多個 IO,此時就是併發 IO 模式。併發 IO 模式提高了效率和速度。
IO 併發機率。單盤,IO 併發機率為 0,因為一塊磁碟同時只可以進行一次 IO 。對於 raid0,2 塊盤情況下,條帶深度比較大的時候(條帶太小不能併發 IO,下面會講到),併發 2 個 IO 的機率為 1/2 。其他情況請自行運算。
IOPS 。一個 IO 所用的時間=尋道時間+資料傳輸時間。 IOPS=IO 併發係數/(尋道時間+資料傳輸時間),由於尋道時間相對傳輸時間,大幾個數量級,所以影響 IOPS 的關鍵因素,就是降底尋道時間,而在連續 IO 的情況下,尋道時間很短,僅在換磁軌時候需要尋道。在這個前提下,傳輸時間越少,IOPS 就越高。
每秒 IO 吞吐量。顯然,每秒 IO 吞吐量=IOPS 乘以平均 IO SIZE 。 Io size 越大,IOPS 越高,每秒 IO 吞吐量就越高。設磁頭每秒讀寫資料速度為 V,V 為定值。則 IOPS=IO 併發係數/(尋道時間+IO SIZE/V),代入,得每秒 IO 吞吐量=IO 併發係數乘 IO SIZE 乘 V/(V 乘尋道時間+IO SIZE)。我們可以看出影響每秒 IO 吞吐量的最大因素,就是 IO SIZE 和尋道時間,IO SIZE 越大,尋道時間越小,吞吐量越高。相比能顯著影響 IOPS 的因素,只有一個,就是尋道時間。
目前磁碟都是機械方式運作的,主要體現在磁碟讀寫前尋找磁軌的過程。磁碟自帶的讀寫 WordPress 加速快取大小,對於磁碟讀寫速度至關重要。讀寫速度快的磁碟,通常都帶有較大的讀寫 WordPress 加速快取。磁碟的尋道過程是機械方式,決定了其隨機讀寫速度將明顯低於順序讀寫。在我們做系統設計和實現時,需要考慮到磁碟的這一特性。
FastDFS 是一個開源的高效分散式檔案系統,它最初的實現,檔案是按 hash 方式隨機分佈到多個目錄中的,後來增加了順序存放的做法。透過對比測試,發現檔案按目錄順序儲存,寫檔案 IO 效率明顯高於按目錄隨機儲存。
目前磁碟順序讀取的速度並不差,比如普通硬碟的 IO 可以達到每秒 40~60MB,好一些的硬碟可以達到每秒 100MB 左右。在多程式或多執行緒併發讀取磁碟的情況下,隨著併發數的增加,磁碟 IO 效率將大大下降。主要是因為每次讀寫,磁軌可能存在較大的偏移,磁軌定址時間加大,導致磁碟 IO 效能急劇下降。對於這種場景,最佳化方案是儘可能減少併發讀寫的程式數或執行緒數。可以用鎖的機制,也可以採用專門的磁碟 IO 執行緒來對磁碟進行讀寫。 FastDFS 2.x 版本,磁碟讀寫就採用了專門的執行緒來完成。
為了充分發揮多塊磁碟的效率,不建議使用傳統的 RAID 方式。比較好的做法是每塊磁碟單獨 mount,透過程式來控制對多塊磁碟進行併發讀寫。採用單盤 mount,檔案的備份和冗餘可以透過多臺機器實現。
檔案數多了之後,比如達到上千萬個檔案,當隨機訪問眾多檔案時,檔案系統的效能會急劇下降。業界流行的做法是將多個小檔案合併儲存到一個大檔案中的方式來降低檔案數。 FastDFS 3.0 支援將多個小檔案合併儲存到一個較大檔案中,目前開發進展比較順利,預計 5 月份可以釋出 3.0 版本。
提升磁碟 IO 的另外一個技巧,一次儘可能多寫入或多讀取。也就是說,將程式的讀寫 buffer 設定得儘可能大一些。例如日誌或者 redo log 的寫入,不是每次呼叫都直接寫磁碟,而是先 WordPress 加速快取到記憶體中,等 buffer 滿了再寫入磁碟,也可以定時寫入磁碟。
作業系統和 C 庫函式通常會對寫入的檔案內容做 WordPress 加速快取,以減少實際寫檔案的次數。直接呼叫系統函式 fsync 或 C 函式 fflush 將使系統的 WordPress 加速快取機制失效,此時將強制把內容刷到磁碟上。除非必需,否則不要執行強制刷盤操作。
注:如果沒有特別說明,文中說的磁碟指的是硬碟。