最佳化永久磁碟效能

最佳化永久磁碟

永久磁碟可提供磁碟類型表所述的效能,但虛擬機器必須產生足夠用量才能達到效能上限。根據效能需求將永久磁碟的磁碟區調整大小後,應用程式和作業系統可能需要經過微調。

在下節中,我們將說明幾個可微調以提高效能的重要元素,及如何將其中幾種元素應用於特定類型的工作負載。

將高 I/O 負載範圍限制為 50 TB

高 I/O 負載在範圍限制為 50 TB 時可達到最高效能。 為了提高效能,如果不同永久磁碟的範圍限制總和在 50 TB 以下,系統會視為單一的 50 TB 範圍限制。此處所稱的「範圍」,指的是單一實體磁碟上邏輯區塊位址的連續範圍。

停用延遲初始化並啟用 DISCARD 指令

永久磁碟支援 DISCARD 或 TRIM 指令,這類指令可讓作業系統在區塊不再使用時通知磁碟。有了對 DISCARD 指令的支援,OS 就能將磁碟區塊標示為不再需要,而不會因為將區塊零化而產生費用。

在大部分的 Linux 作業系統上,您必須在將永久磁碟掛接至執行個體時啟用 DISCARD。Windows Server 2012 R2 執行個體則會在您掛接永久磁碟時預設啟用 DISCARD。Windows Server 2008 R2 不支援 DISCARD。

啟用 DISCARD 可提高一般執行階段效能,同時還可提高磁碟首次掛接時的效能。將磁碟的整個磁碟區格式化可能相當費時,所以常見的做法是「延遲格式化」。延遲格式化的缺點是您往往得在首次掛接磁碟區時支付費用。只要停用延遲初始化並啟用 DISCARD 指令,您就能快速進行格式化及掛接。

  • 在格式化過程中將下列參數傳送至 mkfs.ext4,即可停用延遲初始化並啟用 DISCARD:

    -E lazy_itable_init=0,lazy_journal_init=0,discard
    

    lazy_journal_init=0 參數不支援含有 CentOS 6RHEL 6 映像檔的執行個體。針對這類執行個體,將永久磁碟格式化時請不要使用該參數。

    -E lazy_itable_init=0,discard
    
  • 在掛接時啟用 DISCARD 指令,將下列標記傳送至掛接指令:

    -o discard
    

永久磁碟在啟用 discard 選項時可順利運作。不過,除了使用 discard 選項以外,您也可以選擇定期執行 fstrim。如果您不使用 discard 選項,請先執行 fstrim 再建立磁碟快照。修整作業系統可讓您建立較小的快照映像檔,進而減少儲存快照的費用。

I/O 佇列深度

許多應用程式可調整 I/O 佇列深度。佇列深度越大,IOPS 就越高,但延遲也可能因此增加。佇列深度越小,每次 I/O 延遲就越低,但可能會降低最大 IOPS。

提前讀取快取

為改善 I/O 效能,作業系統會採用提前讀取這類技巧,在這種情況下,記憶體中讀入的檔案數量比所要求的還多,因為系統會假設後續的讀取作業可能需要這些資料。提前讀取量越多,總處理量就越高,但記憶體和 IOPS 會受到影響。提前讀取量越少,IOPS 就越高,但總處理量會受影響。

在 Linux 系統上,您可以透過 blockdev 指令取得及設定提前讀取值:

$ sudo blockdev --getra /dev/[DEVICE_ID]
$ sudo blockdev --setra [VALUE] /dev/[DEVICE_ID]

提前讀取值為 <desired_readahead_bytes> / 512 個位元組。

舉例來說,假設需要 8 MB 的提前讀取量,而 8 MB 是 8388608 個位元組 (8 * 1024 * 1024)。

8388608 bytes / 512 bytes = 16384

因此,blockdev 應設為 16384

$ sudo blockdev --setra 16384 /dev/[DEVICE_ID]

釋出 CPU

讀取和寫入永久磁碟時需要 VM 的 CPU 週期。如要達到高度且一致的 IOPS 等級,則必須釋出 CPU 來處理 I/O。

IOPS 導向的工作負載

SQL 或 NoSQL 資料庫都有隨機存取資料的使用模式。 Google建議對於 IOPS 導向的工作負載使用下列值:

  • 每 400 到 800 IOPS 的 I/O 佇列深度值設為 1,如果是大型磁碟區則最多可提高到 64

  • 針對每 2,000 隨機讀取 IOPS 使用 1 個空閒的 CPU,並針對每 2,500 隨機寫入 IOPS 使用 1 個空閒的 CPU

MongoDBApache Cassandra 和其他資料庫應用程式的最佳做法文件一般會建議使用較低的提前讀取值。

總處理量導向的工作負載

串流作業 (例如 Hadoop 工作) 受惠於快速的循序讀取能力,而較大的 I/O 可提高串流效能。就以總處理量為導向的工作負載而言,建議您使用大小在 256 KB 以上的 I/O。

最佳化標準永久磁碟效能

如要讓標準永久磁碟一致地達到最大總處理量等級,請使用下列最佳做法:

  • 盡量使用平行循序 IO 串流

    請在標準永久磁碟上使用循序 IO,因為系統採用的設計是要最佳化循序磁碟存取的 IO 效能,就像真正的 HDD 硬碟一樣。

    在多個循序串流間分配 IO 將可大幅提升效能。為達到最佳一致性等級,請使用 8 個以上的循序串流。

  • 使用較大的 IO 大小

    標準永久磁碟可提供符合限制的極高總處理量。為確保不讓 IOPS 限制與延遲時間變成應用程式效能的瓶頸,請使用 256 KB 以上的最小 IO 大小。

    如為分散式檔案系統應用,請使用較大的分段大小。使用較大分段大小 (例如 4MB 以上) 的隨機 IO 工作負載將可在標準永久磁碟上達到絕佳效能,因為工作負載仿效多個循序串流磁碟存取的方式極為接近。

  • 確保提供給 I/O 的平行運作數充足

    請盡量使用較大的佇列深度,以利用 OS 的平行運作功能。如為標準永久磁碟,使用夠大的佇列深度格外重要,這樣才能達到符合限制的總處理量,而不會讓 IO 延遲時間變成應用程式的瓶頸。

最佳化 SSD 永久磁碟效能

各個磁碟類型的效能表說明了固態永久磁碟應可達到的效能。如要最佳化應用程式和 VM 執行個體以達到此速度,請使用下列最佳做法:

  • 確保應用程式產生足夠的 I/O

    如果應用程式產生的 IOPS 少於先前表中所述的上限,就無法達到該 IOPS 等級。舉例來說,在 500 GB 的磁碟上,IOPS 上限應為 15,000 IOPS。不過,如果產生的 IOPS 少於這個值,或 I/O 作業大於 8 KB,就無法達到 15,000 IOPS。

  • 確保提供給 I/O 的平行運作數充足

    請使用夠大的佇列深度,以便利用 OS 的平行運作功能。如果您提供 1,000 IOPS,但是在佇列深度為 1 的情況下以同步方式進行,所達到的 IOPS 就會遠低於表中所列的上限。應用程式每 400 到 800 IOPS 的佇列深度應至少要有 1。

  • 確保產生 I/O 的執行個體上有足夠的可用 CPU

    如果 VM 執行個體的 CPU 不足,應用程式將無法達到先前所述的 IOPS。我們建議每 2,000 到 2,500 IOPS 的預期流量應要有 1 個可用 CPU。

  • 確保應用程式已經過最佳化,在大型磁碟上有合理的暫時資料本地性

    如果應用程式會在短時間內存取分散在磁碟中不同部分的資料 (每個 vCPU 數百 GB),就無法達到最佳 IOPS。如要獲得最佳效能,請針對暫時資料本地性進行最佳化,要考量的因素包括磁碟片段化和所存取磁碟部分的隨機性。

  • 確保您已根據自己的特定需求設定 OS 中的 I/O 排程器

    在 Linux 系統上,您可以將 I/O 排程器設為 noop,以便在採用 SSD 的裝置上達到最高的 IOPS。

基準化 SSD 永久磁碟效能

下列指令假設您使用裝置大小為 2,500 GB 的 SSD 永久磁碟。如果您的裝置大小不同,請修改 --filesize 引數。必須使用此磁碟大小才能達到 32 vCPU VM 總處理量上限。

    # Install dependencies
    sudo apt-get update
    sudo apt-get install -y fio
  1. 為磁碟填充非零資料。空白區塊與含資料區塊的永久磁碟讀取作業有不同的延遲狀況。 建議您執行任何讀取延遲基準前先填充磁碟。

    # Running this command causes data loss on the second device.
    # We strongly recommend using a throwaway VM and disk.
    sudo fio --name=fill_disk \
      --filename=/dev/sdb --filesize=2500G \
      --ioengine=libaio --direct=1 --verify=0 --randrepeat=0 \
      --bs=128K --iodepth=64 --rw=randwrite
    
  2. 測試寫入頻寬。搭配多個平行串流 (8 個以上) 使用循序寫入,且 I/O 大小為 1MB,I/O 深度則為 64 以上。

    # Running this command causes data loss on the second device.
    # We strongly recommend using a throwaway VM and disk.
    sudo fio --name=write_bandwidth_test \
      --filename=/dev/sdb --filesize=2500G \
      --time_based --ramp_time=2s --runtime=1m \
      --ioengine=libaio --direct=1 --verify=0 --randrepeat=0 \
      --bs=1M --iodepth=64 --rw=write --numjobs=8 --offset_increment=100G
    
  3. 測試寫入 IOPS。如要達到 PD 磁碟 IOPS 上限,請務必維持夠深的 I/O 佇列。舉例來說,如果寫入延遲為 1 毫秒,則針對每項傳輸中的 I/O,VM 最高可達到 1,000 IOPS。 如要達到 15,000 IOPS,VM 必須維持至少 15 個傳輸中的 I/O。如果您的磁碟和 VM 能夠達到 30,000 IOPS,則至少要有 30 個傳輸中的 I/O。如果 I/O 大小超過 4 KB,VM 可能會在達到 IOPS 上限前先達到頻寬上限。

    # Running this command causes data loss on the second device.
    # We strongly recommend using a throwaway VM and disk.
    sudo fio --name=write_iops_test \
      --filename=/dev/sdb --filesize=2500G \
      --time_based --ramp_time=2s --runtime=1m \
      --ioengine=libaio --direct=1 --verify=0 --randrepeat=0 \
      --bs=4K --iodepth=64 --rw=randwrite
    
  4. 測試寫入延遲。測試 I/O 延遲時,請確保 VM 未達到頻寬或 IOPS 上限,否則觀察到的延遲無法反映出實際的永久磁碟 I/O 延遲狀況。舉例來說,如果 I/O 深度為 30 時會達到 IOPS 上限,且 fio 指令會產生兩倍的值,則總 IOPS 會維持不變,回報的 I/O 延遲時間則會加倍。

    # Running this command causes data loss on the second device.
    # We strongly recommend using a throwaway VM and disk.
    sudo fio --name=write_latency_test \
      --filename=/dev/sdb --filesize=2500G \
      --time_based --ramp_time=2s --runtime=1m \
      --ioengine=libaio --direct=1 --verify=0 --randrepeat=0 \
      --bs=4K --iodepth=4 --rw=randwrite
    
  5. 測試讀取頻寬。搭配多個平行串流 (8 個以上) 使用循序讀取,且 I/O 大小為 1MB,I/O 深度則為 64 以上。

    sudo fio --name=read_bandwidth_test \
      --filename=/dev/sdb --filesize=2500G \
      --time_based --ramp_time=2s --runtime=1m \
      --ioengine=libaio --direct=1 --verify=0 --randrepeat=0 \
      --bs=1M --iodepth=64 --rw=read --numjobs=8 --offset_increment=100G
    
  6. 測試讀取 IOPS。如要達到 PD 磁碟 IOPS 上限,請務必維持夠深的 I/O 佇列。如果 I/O 大小超過 4 KB,VM 可能會在達到 IOPS 上限前先達到頻寬上限。如要達到最大 10 萬次讀取 IOPS,請為這項測試指定 --iodepth=256

    sudo fio --name=read_iops_test \
      --filename=/dev/sdb --filesize=2500G \
      --time_based --ramp_time=2s --runtime=1m \
      --ioengine=libaio --direct=1 --verify=0 --randrepeat=0 \
      --bs=4K --iodepth=256 --rw=randread
    
  7. 測試讀取延遲。請務必為磁碟填充資料,這樣才能測出真實的延遲時間。此外,請確保 VM 在測試期間未達到 IOPS 或總處理量上限,因為永久磁碟達到飽和上限後,就會拒絕連入 I/O,導致 I/O 延遲出現人為增加的情況。

    sudo fio --name=read_latency_test \
      --filename=/dev/sdb --filesize=2500G \
      --time_based --ramp_time=2s --runtime=1m \
      --ioengine=libaio --direct=1 --verify=0 --randrepeat=0 \
      --bs=4K --iodepth=4 --rw=randread
    
  8. 測試循序讀取頻寬。

    sudo fio --name=read_bandwidth_test \
      --filename=/dev/sdb --filesize=2500G \
      --time_based --ramp_time=2s --runtime=1m \
      --ioengine=libaio --direct=1 --verify=0 --randrepeat=0 \
      --numjobs=4 --thread --offset_increment=500G \
      --bs=1M --iodepth=64 --rw=read
    
  9. 測試循序寫入頻寬。

    sudo fio --name=write_bandwidth_test \
      --filename=/dev/sdb --filesize=2500G \
      --time_based --ramp_time=2s --runtime=1m \
      --ioengine=libaio --direct=1 --verify=0 --randrepeat=0 \
      --numjobs=4 --thread --offset_increment=500G \
      --bs=1M --iodepth=64 --rw=write
    

後續步驟

本頁內容對您是否有任何幫助?請提供意見:

傳送您對下列選項的寶貴意見...

這個網頁
Compute Engine 說明文件