返回文章列表

MongoDB磁碟IO效能最佳化策略

本文探討MongoDB磁碟IO效能最佳化策略,涵蓋硬體選型、RAID組態、雲端儲存方案以及MongoDB I/O操作特性。從減少IO需求、理解延遲與吞吐量、順序與隨機IO的區別開始,逐步引導讀者認識磁碟硬體技術(HDD、SSD)以及不同儲存層級的效能差異。文章也分析了RAID組態對效能的影響,特別指出RAID

資料函式庫 效能調校

在最佳化資料函式庫設計和查詢、調整記憶體組態後,磁碟IO最佳化是MongoDB效能調校的最後一步。由於磁碟調優通常涉及硬體採購和資料重組,因此應在確認工作負載和記憶體已最佳化後進行。理解磁碟IO的延遲和吞吐量,以及順序IO和隨機IO的差異,是選擇合適硬體的基礎。磁性硬碟(HDD)和固態硬碟硬碟(SSD)各有優劣,SSD因其低延遲和高隨機IO效能更適合MongoDB。SSD的儲存層級(SLC、MLC)和介面(SATA、PCIe/NVMe)也會影響效能。選擇儲存陣列時,應仔細評估RAID等級,避免RAID 5的寫入懲罰影響效能。在雲端環境中,選擇Provisioned IOPS SSD通常能提供最佳效能。最後,瞭解MongoDB的I/O操作型別(臨時檔案、資料檔案、日誌檔案),並監控相關指標,才能有效最佳化MongoDB的整體效能。

磁碟IO最佳化

在前面的章節中,我們已經盡可能地避免磁碟IO。透過最佳化資料函式庫設計和調整查詢,我們最小化了工作負載需求,從而減少了對MongoDB的邏輯IO需求。最佳化記憶體減少了轉化為磁碟活動的工作負載量。如果您已經應用了前幾章的實踐,那麼您的實體磁碟需求已經被最小化:現在是時候最佳化磁碟子系統以滿足這一需求了。

減少IO需求應該幾乎總是在磁碟IO調優之前進行。

磁碟調優通常在時間、金錢和資料函式庫可用性方面都很昂貴。它可能涉及購買昂貴的新磁碟裝置和執行耗時的資料重新組織,這些都會導致可用性和效能的降低。如果您在調整工作負載和記憶體之前嘗試這些操作,那麼您可能會不必要地為不切實際的需求最佳化磁碟。

IO基礎知識

在我們研究MongoDB如何執行磁碟IO操作以及您可能佈署的各種IO系統之前,回顧一些適用於任何磁碟IO系統和任何資料函式庫系統的基本概念是值得的。

延遲和吞吐量

磁碟裝置有兩個從效能角度關心的基本特徵:延遲和吞吐量。

延遲描述了從磁碟檢索單個資訊項所需的時間。對於旋轉磁碟驅動器,這是將磁碟盤旋轉到正確位置所需的時間(旋轉延遲),加上將讀/寫頭移動到正確位置所需的時間(尋道時間),再加上將資料從磁碟傳輸到伺服器所需的時間。對於固態硬碟硬碟,沒有機械尋道時間或旋轉延遲,只有傳輸時間。

IO吞吐量描述了磁碟裝置在給定單位時間內可以執行的IO操作次數。吞吐量通常以每秒IO操作次數(IOPS)表示。

對於單個磁碟裝置(尤其是SSD),吞吐量和延遲密切相關。吞吐量直接由延遲決定——如果每個IO操作需要千分之一秒,那麼吞吐量應該是1000 IOPS。然而,當多個裝置組合成一個邏輯卷時,延遲和吞吐量之間的關係就不那麼直接了。此外,在磁性磁碟中,順序讀取的吞吐量遠高於隨機讀取。

對於大多數資料函式庫伺服器,資料儲存在多個磁碟裝置上,並跨相關磁碟進行“條帶化”。在這種情況下,IO頻寬是IO操作型別(隨機vs.順序)、服務時間和磁碟數量的函式。例如,一個包含十個磁碟的完美條帶化磁碟陣列,每個磁碟的服務時間為10毫秒,其隨機IO頻寬約為1000 IOPS(每個磁碟100 IOPS乘以十個磁碟)。

佇列

當磁碟空閒並等待請求時,磁碟裝置的服務時間保持相當可預測。服務時間會根據磁碟的內部快取以及(對於磁性磁碟)讀/寫頭需要移動多遠來取得相關資料而有所不同。但總的來說,回應時間將在磁碟製造商參照的範圍內。

然而,隨著請求數量的增加,一些請求將不得不等待其他請求被處理。隨著請求率的增加,最終會形成一個佇列。就像在繁忙的超市一樣,您很快就會發現您在佇列中花費的時間比實際接受服務的時間還要多。

由於佇列的存在,當磁碟系統接近滿負荷時,磁碟延遲會急劇增加。當磁碟變成100%繁忙時,任何額外的請求只會增加佇列的長度和服務時間,而不會增加吞吐量。

這裡的教訓是,隨著我們增加磁碟的吞吐量,延遲也會增加。圖12-1說明瞭吞吐量和延遲之間的典型關係:增加吞吐量通常與增加延遲相關。最終,無法實作更多的吞吐量;在這一點上,任何請求率的增加都會增加延遲,而不會增加吞吐量。

延遲 vs. 吞吐量

此圖示顯示了隨著吞吐量的增加,延遲也隨之增加的關係。

圖表說明

圖12-1. 延遲 vs. 吞吐量

注意:延遲和吞吐量是相關的:增加對磁碟裝置的吞吐量或需求通常會導致延遲的增加。為了最小化延遲,可能需要以低於最大吞吐量的方式執行磁碟。

如果單個磁碟的最大IOPS有限,那麼要實作更高的IO吞吐率,就需要佈署更多的實體磁碟。與由相對複雜的佇列理論計算所控制的延遲計算不同,計算所需磁碟裝置數量的公式很簡單。如果單個磁碟在提供可接受的延遲的情況下可以執行100 IOPS,而我們認為需要提供500 IOPS,那麼我們可能需要至少五個磁碟裝置。

磁碟I/O效能最佳化與儲存技術解析

在資料函式庫系統中,磁碟I/O(輸入/輸出)效能是影響整體系統效能的關鍵因素之一。磁碟I/O效能主要由系統中實體磁碟裝置的數量決定。為了提高I/O效能,增加磁碟陣列中的實體磁碟數量是一種常見的方法。

然而,確定磁碟裝置的「舒適」I/O速率——即能夠提供可接受服務時間的I/O速率——並非總是容易的事。磁碟供應商通常會提供最小延遲和最大吞吐量的規格,前者是指在沒有磁碟爭用情況下的延遲,後者則是指忽略服務時間限制下的吞吐量。幾乎所有的磁碟供應商提供的吞吐量資料都是在磁碟100%繁忙狀態下測得的。

順序I/O與隨機I/O

對於資料函式庫工作負載,I/O操作可以根據兩個維度進行分類別:讀取與寫入I/O,以及順序與隨機I/O。

  • 順序I/O 發生在資料區塊按順序讀取的情況下。例如,當我們使用集合掃描讀取集合中的所有檔案時,就是在執行順序I/O。
  • 隨機I/O 則是在任意順序下存取資料頁。例如,當我們透過索引查詢檢索單個檔案時,就是在執行隨機I/O。

資料函式庫I/O分類別

| | 讀取 | 寫入 | |



|















-|















-| | 隨機 | 使用索引讀取個別檔案 | 將快取中的資料寫入磁碟(例如,當資料被替換出快取時) | | 順序 | 使用完整集合掃描讀取集合中的所有檔案 | 將資料批次載入資料函式庫,或寫入WiredTiger日誌或Oplog |

磁碟硬體技術

本文將回顧構成儲存子系統的各種硬體元件,從單個磁性或SSD磁碟到硬體和根據雲的儲存陣列。

磁性硬碟(HDD)

磁性硬碟驅動器(HDD)長期以來一直是主流電腦裝置的基本元件。其基本技術自1950年代引入以來保持相對穩定:一個或多個碟片包含代表資訊位的磁性電荷。這些磁性電荷由致動器臂讀取和寫入,致動器臂移動到碟片半徑上的特定位置,然後等待碟片旋轉到適當的位置。讀取資訊所需時間是移動磁頭到位所需時間(尋道時間)、旋轉資訊到位所需時間(旋轉延遲)和透過磁碟控制器傳輸資訊所需時間(傳輸時間)的總和。

固態硬碟硬碟(SSD)

固態硬碟硬碟(SSD)將資料儲存在半導體單元中,沒有移動部件。它們提供遠低於磁性硬碟的延遲,因為不需要等待機械運動。SSD的儲存架構有利於不同型別的I/O操作,瞭解這些有助於我們為SSD佈署做出最佳決策。

SSD儲存層級

SSD具有三級儲存層級。個別資訊位儲存在單元格中。在單層單元格(SLC)SSD中,每個單元格只儲存一個位元。在多層單元格(MLC)中,每個單元格可能儲存兩個或更多位元的資訊。單元格排列成頁面(通常為4K大小),頁面再組成區塊(大小在128K到1M之間)。

###效能差異與技術選型

  • HDD與SSD的效能差異 不僅僅體現在讀取速度上。HDD的架構有利於順序讀寫操作,而SSD則對隨機讀寫操作具有更好的支援。
  • 技術選型考量 在選擇儲存技術時,需要根據具體的工作負載和效能需求進行權衡。對於某些系統,使用磁碟或SSD與磁碟的組合可能提供最佳的價格/效能比。

程式碼範例:模擬磁碟I/O效能測試

import random
import time

def simulate_disk_io(access_type, num_operations):
    if access_type == 'sequential':
        # 模擬順序I/O
        start_time = time.time()
        for i in range(num_operations):
            # 假設這裡進行順序讀寫操作
            pass
        end_time = time.time()
        return end_time - start_time
    elif access_type == 'random':
        # 模擬隨機I/O
        start_time = time.time()
        for _ in range(num_operations):
            # 假設這裡進行隨機讀寫操作
            random.randint(0, num_operations)  # 模擬隨機存取
        end_time = time.time()
        return end_time - start_time

# 測試10000次操作下的順序與隨機I/O效能
num_operations = 10000
sequential_time = simulate_disk_io('sequential', num_operations)
random_time = simulate_disk_io('random', num_operations)

print(f"順序I/O {num_operations} 次操作耗時: {sequential_time} 秒")
print(f"隨機I/O {num_operations} 次操作耗時: {random_time} 秒")

內容解密:

  1. simulate_disk_io函式:此函式用於模擬不同型別的磁碟I/O操作,包括順序和隨機存取。
  2. access_type引數:決定了模擬的I/O型別,可以是'sequential''random'
  3. num_operations引數:指定了要模擬的I/O操作次數。
  4. 時間測量:透過記錄操作開始和結束的時間,計算出完成指定次數I/O操作所需的總時間。
  5. random.randint(0, num_operations):用於模擬隨機I/O操作,透過生成隨機數來模擬對不同資料位置的存取。

SSD效能與架構對MongoDB的影響

寫入效能的重要性

SSD的頁面和區塊結構對於效能至關重要,因為快閃記憶體的寫入操作具有特殊性質。讀取操作和初始寫入只需要單一頁面IO,但修改頁面內容需要擦除整個區塊並重新寫入。即使初始寫入比讀取慢,區塊擦除操作的速度更是慢了許多,大約需要兩毫秒。圖12-3展示了頁面定址、初始頁面寫入和區塊擦除的大致時間。

寫入耐久性的限制

SSD的寫入操作還有另一個後果:經過一定次數的寫入後,儲存單元可能會變成不可用。寫入耐久性的限制因SSD而異,但通常在低階MLC裝置的10,000次迴圈和高階SLC裝置的1,000,000次迴圈之間。

垃圾回收與磨損平衡

企業級SSD製造商努力避免擦除操作帶來的效能損失和寫入耐久性帶來的可靠性問題。他們使用先進的演算法來最小化擦除操作並均勻分配寫入操作。在企業級SSD中,透過使用空閒列表和垃圾回收來避免擦除操作。在更新資料時,SSD會將待修改的區塊標記為無效,並將更新後的內容複製到從空閒列表中取得的空區塊。稍後,垃圾回收例程會回收無效區塊,並將其放入空閒列表以供後續操作使用。

SATA與PCIe介面的比較

SSD通常以三種形式佈署:

  • SATA或SAS型快閃磁碟機採用與其他磁性硬碟相同的外形尺寸,使用傳統的SAS或SATA聯結器。
  • PCIe型SSD直接連線到電腦主機板的PCIe介面。NVMe(非揮發性記憶體快線)規範描述了SSD如何連線到PCIe,因此這些型別的磁碟機通常被稱為NVMe SSD。
  • 快閃儲存伺服器在機架式伺服器中提供多個SSD,並配備多個高速網路介面卡。

SSD的建議

對於MongoDB佈署,我們建議盡可能使用根據SSD的儲存。只有在擁有大量「冷」資料(即很少被存取的資料)的情況下,磁性硬碟才會是合適的選擇。PCIe型SSD(NVMe)比SATA型SSD更快,而單層儲存單元(SLC)SSD又比多層儲存單元(MLC)SSD更快。

儲存陣列與RAID等級

在生產環境中,MongoDB通常不會直接寫入單一裝置,而是存取多個磁碟,這些磁碟被組合成邏輯卷或儲存陣列。RAID(冗餘磁碟陣列)定義了多種條帶化和冗餘方案。常見的RAID等級包括:

  • RAID 0:條帶化磁碟,將邏輯磁碟分散到多個實體磁碟上,以提高隨機IO效能,但不提供冗餘。
  • RAID 1:磁碟映象,將邏輯磁碟複製到兩個實體磁碟上,以提高讀取效能並提供容錯能力。
  • RAID 5:將資料和同位元檢查資訊分散到多個實體磁碟上,以提供容錯能力和合理的效能。
  • RAID 10(或RAID 0+1):結合RAID 0和RAID 1,提供條帶化和映象,以兼顧效能和容錯能力。

RAID等級比較

RAID等級描述優點缺點
RAID 0條帶化高效能無冗餘
RAID 1映象高讀取效能、容錯能力儲存空間利用率低
RAID 5資料和同位元檢查條帶化容錯能力、合理的效能寫入效能較低
RAID 10條帶化和映象結合高效能、容錯能力較高的成本

在選擇RAID等級時,需要根據實際需求和優先順序進行權衡。例如,如果優先考慮效能,可以選擇RAID 0或RAID 10;如果優先考慮容錯能力,可以選擇RAID 1或RAID 5。

磁碟IO與RAID組態最佳實踐

RAID技術概述與效能考量

RAID(獨立磁碟冗餘陣列)技術主要用於提升儲存系統的效能與可靠性。常見的RAID組態包括RAID 0、RAID 5和RAID 10等。在資料函式庫伺服器中,RAID組態的選擇對效能有著重大影響。

RAID 5的效能瓶頸

RAID 5因其經濟高效的架構而被廣泛採用,但對於資料函式庫伺服器來說卻並非最佳選擇。RAID 5在寫入操作時會產生「寫入懲罰」,因為每次寫入都需要讀取原始資料區塊和校驗區塊,並進行更新,總計涉及四次IO操作。這使得檢查點、驅逐和日誌IO的效能嚴重下降。

RAID 5寫入懲罰的影響

  • 寫入效能下降:RAID 5的寫入操作涉及多次IO,導致效能下降。
  • 磁碟故障時的重建:當某個磁碟故障時,所有剩餘磁碟都需要被存取以重建邏輯檢視,進一步影響效能。
  • 不適合大多數資料函式庫:由於寫入懲罰,RAID 5不適合大多數資料函式庫,尤其是在需要頻繁寫入操作的場景中。

非揮發性快取在RAID 5中的應用

非揮發性快取可以緩解RAID 5的寫入懲罰問題。這種快取具有電池備份,能夠在斷電時保護資料。當資料被寫入快取後,磁碟裝置可以立即報告寫入完成,而實際的寫入操作可以延遲進行。

非揮發性快取的優勢與限制

  • 提升寫入效能:非揮發性快取可以顯著提升寫入效能,尤其是在需要確認資料已提交到磁碟的應用中。
  • 緩解寫入懲罰:對於突發性的寫入操作,非揮發性快取可以有效緩解RAID 5的寫入懲罰。
  • 持續寫入時的效能下降:如果寫入操作持續進行,快取最終會被填滿,導致效能下降到與底層磁碟相同的水平。

自建RAID陣列

使用者可以使用mdadm命令在Linux系統上建立自己的RAID陣列。例如,建立一個由兩個裸裝置組成的RAID 0條帶卷:

[root@Centos8 etc]# mdadm --create --verbose /dev/md0 --level=0 --name=raid1a --raid-devices=2 /dev/sdh /dev/sdi
[root@Centos8 etc]# mkfs -t xfs /dev/md0
[root@Centos8 etc]# mkdir /mnt/raid1a
[root@Centos8 etc]# mount /dev/md0 /mnt/raid1a

自建RAID陣列的靈活性

  • 多種RAID組態:使用者可以根據需求建立不同型別的RAID組態,如RAID 0、RAID 1或RAID 10。
  • 直接附加儲存:對於直接附加儲存裝置,自建RAID陣列提供了靈活性和控制權。

硬體儲存陣列

許多MongoDB資料函式庫使用外部儲存陣列,這些陣列透過專用網路介面連線到伺服器,提供區塊裝置功能。硬體儲存陣列通常包含非揮發性記憶體快取,以確保資料在斷電時不會丟失。

硬體儲存陣列的考量因素

  • 網路延遲:使用硬體儲存陣列會增加網路延遲,每次IO請求都需要透過網路介面。
  • 內部組態的重要性:儲存陣列的內部組態(如RAID級別、磁碟型別)對效能有著重大影響。
  • RAID 5的經濟性誤區:儘管硬體廠商可能宣稱RAID 5更經濟,但實際上它可能增加每秒輸入/輸出操作(IOPS)的成本。

磁碟I/O效能最佳化

在現代資料函式庫系統中,磁碟I/O(輸入/輸出)效能直接影響整體系統的效能與效率。MongoDB作為一個高效能的NoSQL資料函式庫,其對磁碟I/O的需求尤為重要。本章將探討如何最佳化MongoDB的磁碟I/O效能,包括硬體選擇、雲端儲存組態以及MongoDB的I/O操作特性。

硬體選擇與I/O效能

在選擇硬體時,瞭解不同儲存裝置的I/O特性至關重要。一般來說,固態硬碟硬碟(SSD)比傳統硬碟(HDD)具有更好的I/O效能。然而,不同的SSD組態也會影響效能。

  • RAID組態:RAID 5雖然在儲存容量上看似划算,但其寫入效能可能會成為瓶頸。選擇合適的RAID組態需要平衡儲存成本和I/O效能需求。
  • SSD選擇:使用SSD可以大幅提升I/O效能,尤其是對於隨機讀寫操作。選擇高品質的SSD,並根據實際需求組態足夠的IOPS(每秒輸入/輸出操作次數)。

雲端儲存組態

在雲端環境中,硬體架構通常被抽象化,雲供應商提供各種區塊儲存裝置,每種裝置都有特定的延遲和吞吐量服務等級。

Amazon AWS磁碟區型別

磁碟區型別描述
General Purpose SSD這些磁碟區根據商用SSD,I/O限制取決於所請求的GB儲存量。
Provisioned IOPS SSD提供特定的I/O水平,與所組態的儲存量無關。
Throughput Optimized HDD高效能磁碟,針對順序讀寫操作進行最佳化。
Cold HDD廉價磁碟,針對低成本儲存進行最佳化。
Instance Store直接連線至實體機器的磁碟,資料在例項故障時會遺失。

對於MongoDB佈署,通常建議選擇Provisioned IOPS SSD,因為它提供了可預期的高I/O效能。

MongoDB的I/O操作

MongoDB使用WiredTiger作為預設的儲存引擎,主要執行三種I/O操作:

  1. 臨時檔案I/O:當進行磁碟排序或根據磁碟的聚合操作時,會寫入臨時檔案至 _tmp 目錄。
  2. 資料檔案I/O:WiredTiger讀取和寫入集合和索引檔案。索引檔案的存取通常是隨機的,而集合檔案的存取可能是隨機或順序的。
  3. 日誌檔案I/O:WiredTiger儲存引擎寫入預寫日誌檔案,這些操作是順序寫入。

圖12-7 MongoDB I/O架構圖

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

title MongoDB磁碟IO效能最佳化策略

package "資料庫架構" {
    package "應用層" {
        component [連線池] as pool
        component [ORM 框架] as orm
    }

    package "資料庫引擎" {
        component [查詢解析器] as parser
        component [優化器] as optimizer
        component [執行引擎] as executor
    }

    package "儲存層" {
        database [主資料庫] as master
        database [讀取副本] as replica
        database [快取層] as cache
    }
}

pool --> orm : 管理連線
orm --> parser : SQL 查詢
parser --> optimizer : 解析樹
optimizer --> executor : 執行計畫
executor --> master : 寫入操作
executor --> replica : 讀取操作
cache --> executor : 快取命中

master --> replica : 資料同步

note right of cache
  Redis/Memcached
  減少資料庫負載
end note

@enduml

最佳化建議

  1. 根據I/O需求選擇硬體或雲端儲存組態,而非僅考慮儲存容量。
  2. 監控MongoDB的日誌,瞭解是否有大量的磁碟排序或聚合操作,這些操作可能會導致臨時檔案I/O增加。
  3. 合理組態慢查詢日誌,以便發現可能導致高I/O操作的查詢。