コンテンツにスキップ

記憶域スペースとReFS

記憶域スペース

まず、記憶域スペースについては、私の記事よりも下記の記事を読む方がわかりやすいです。
記憶域スペース - 薩摩藩中仙道蕨宿別邸

記憶域スペースとはWindows8, 10/Windows Server 2012以降で利用できる、ストレージの冗長化機能です。
複数のHDDやSSDを束ねて、冗長性のあるディスクとして利用することができます。

似たような機能としてソフトウェアRAIDがありますが、下記の点が異なります。

  • サイズの異なるディスクの組み合わせでも利用できる
  • 実ディスクのサイズ以上のボリュームを作成できる
  • 運用開始後にHDD/SSDの追加して、容量の追加ができる
  • データ重複除去機能がある

ソフトウェアRAIDよりは、LinuxのLVMが近いイメージです。

また、後述のReFSと併せて利用することで、ファイルレベルでの整合性の担保、エラー時の自動修正が可能です。

記憶域スペースの構成要素

  • 物理ディスク(Physical Disk)
    物理的なHDD、SSDを指します。接続方法はSAS,iSCSI,Fiber Channelなどのサーバ向けのものからNVMe,SATA,USBなどでも(一応)構成可能です。
    また、Windows Server 2019ではIntelのOptane DC Persistent MemoryやNVDIMM-Nもサポートしています。

  • 仮想ディスク(Virtual Disk)
    実際にユーザが利用する、冗長化された仮想的なディスクです。
    後述のシンプロビジョニング(Thin Provisioning)という機能を利用することで、物理ディスク以上のサイズの仮想ディスクを作成することもできます。

  • 記憶域プール(Storage Pool)
    物理ディスクをまとめてプールにしたものです。
    ここから物理ディスクを切り出して、仮想ディスクを作成します。

  • 記憶域階層(Storage Tier)
    SSDとHDDなどのアクセス速度の異なる物理ディスクを組み合わせて階層構造をとることで、 SSDを読み取り・書き込みキャッシュのように利用して冗長化によるパフォーマンスの低下を補なうことのできる機能です。
    記憶域階層を使用する場合、SSD階層とHDD階層のそれぞれで異なる冗長化方法を選択することができます。

また、関連する機能として「記憶域スペース ダイレクト」、「記憶域スペース レプリカ」といったものがありますが、ここでは割愛します。

冗長化の種類

記憶域スペースではディスクの冗長化について、下記の4種類から選択できます。

種類 冗長化 利用可能な
ディスク容量
最低限必要な
ディスク本数
シンプル 冗長化を行わない。 物理ディスクと同等 1本
双方向ミラー データを2本のディスクに冗長化する。 物理ディスクの半分 2本
3方向ミラー データを3本のディスクに冗長化する。 物理ディスクの1/3 3本
パリティ データを3本以上のディスクに
分散して冗長化する。
物理ディスクの2/3~7/8 3本
デュアルパリティ データを7本以上のディスクに
分散して冗長化する。
物理ディスクの4/7~ 7本

物理ディスクの割り当て

記憶域スペースでは、2種類のディスク割り当て方式があります。

  • 固定(Fixed)
    仮想ディスク作成時に物理ディスクの割り当てを行う方式。いたってシンプル。

  • シンプロビジョニング(Thin Provisioning)
    仮想ディスク作成時ではなく、データ書き込み時に物理ディスクへの割り当てを行う方式。
    物理ディスクの総容量よりも大きなサイズの仮想ディスクを作成することができ、物理ディスク容量が不足した場合にはプールへディスクを追加するだけでよい。
    反面、仮想ディスクの容量に余裕があるように見えても、物理ディスク容量が不足してデータが書き込めないといったことも発生しうる。

ディスク故障時の回復

記憶域プールに対して、ディスクが故障した場合に自動的に冗長性を回復するための「ホットスペア」ディスクを割り当てることができます。
これにより、ディスクの故障が発生した場合でも、故障前と同じ状態に戻るようになっています。

ただ、ホットスペアを割り当てずに記憶域プールを構成することも可能です。
この場合、ディスク故障時にはプール内の他のディスクにミラーやパリティ情報を分散させて冗長性を回復するようになっています。

構成の例

下記の図では200GBのSSDを2本、500GBのHDDを2本、1TBのHDDを2本を使用して合計サイズ3.4TBのプールを作成しています。
また、HDDが故障したときのために、1TBのHDDをホットスペアとして割り当てています。

図の左上 例1では、記憶域階層を使用して1TBのミラーで冗長化された仮想ディスクを作成しています。 「シンプロビジョニング」を用いずに、仮想ディスクの作成時に1TB×2(ミラーなので2倍)の容量分の物理ディスクを確保しています。

一方、図の右上 例2のように、記憶域階層を用いずに仮想ディスクを作成することもできます。
こちらは「シンプロビジョニング」を用いて、物理ディスクのサイズよりも大きい4TBのパリティで冗長化された仮想ディスクを作成しています。

図: 記憶域スペースの構成例

例1のディスクの構成方法

# プールに設定するSSD/HDDを取得
$PhysicalDisks = Get-PhysicalDisk 200GB-SSD-1, 200GB-SSD-2, 500GB-HDD-1, 500GB-HDD-2, 1TB-HDD-1, 1TB-HDD-2, 1TB-HDD-3
# 記憶域プールを作成
Get-StorageSubSystem | New-StoragePool –FriendlyName '記憶域プール' –PhysicalDisks $PhysicalDisks
# ホットスペアを設定
Set-PhysicalDisk 1TB-HDD-3 -Usase HotSpare

# SSDの記憶域階層を作成
$SSDTier = New-StorageTier -StoragePoolFriendlyName '記憶域プール' -FriendlyName 'SSD階層' -MediaType SSD -ResiliencySettingName Mirror -ProvisioningType Fixed
# HDDの記憶域階層を作成
$HDDTier = New-StorageTier -StoragePoolFriendlyName '記憶域プール' -FriendlyName 'HDD階層' -MediaType HDD -ResiliencySettingName Parity -ProvisioningType Fixed -NumberOfColumns 4
# ReFSのボリュームを作成
# サイズ指定はSSD:200GB、HDD:1TB(バイト単位)
New-Volume -FriendlyName '例1' -WriteCacheSize 16GB -StorageTiers $SSDTier,$HDDTier -StorageTierSizes 214748364800,1099511627776

例2のディスクの構成方法

# プールに設定するSSD/HDDを取得
$PhysicalDisks = Get-PhysicalDisk 200GB-SSD-1, 200GB-SSD-2, 500GB-HDD-1, 500GB-HDD-2, 1TB-HDD-1, 1TB-HDD-2, 1TB-HDD-3
# 記憶域プールを作成
Get-StorageSubSystem | New-StoragePool –FriendlyName '記憶域プール' –PhysicalDisks $PhysicalDisks
# ホットスペアを設定(ここまでは例1と同じ)
Set-PhysicalDisk 1TB-HDD-3 -Usase HotSpare

# NTFSのボリュームを作成
New-Volume -FriendlyName '例2' -StoragePoolFriendlyName '記憶域プール' -FileSystem NTFS -DriveLetter G -Size 4TB -ResiliencySettingName Mirror -ProvisioningType Thin

Resilient File System(ReFS)

Windows Server 2012以降、もしくはWindows10 Pro for WorkstationおよびEnterpriseで利用できるファイルシステムです。
従来のWindowsのファイルシステムであるNTFSと比較して、信頼性・可用性・拡張性に優れているとされています。

個人で利用する場合、Windows10 Pro for Workstationでの利用が最有力の候補となります。

ReFSの特徴

  • 信頼性
    「整合性ストリーム」とオプション機能を利用することで、ファイル読み込み時にチェックサムの検証とエラー修正を行うことができます。
    これは、ボリューム全体、フォルダ単位またはファイル単位で有効化・無効化ができます。
    また、定期的にデータをスキャンし、エラーのチェックと修正を行うことができます。

  • 可用性
    稼働状態でのデータのエラー修正が可能です。

  • 保守性
    もし、ファイルシステムレベルで破損してしまった場合、Windowsに標準でインストールされているrefsutilというツールを用いて、可能な限りのデータ・サルベージを行うことができます。

  • 性能
    コピー・オン・ライトを採用しており、Hyper-Vなどで使用される固定サイズのvhdxファイル作成などは数秒で完了します。
    しかし、細かいファイルアクセスの速度などについてはあまり得意で無く、あくまでサーバなどでの信頼性に重点をおいたものとなっています。
    また、Windows OSの起動ディスクにReFSを採用することはできません。

整合性ストリームの有効化方法

ReFSのボリューム作成した段階では整合性ストリームは無効の状態になっています。
有効化するためには、PowerShell上でSet-FileIntegrityコマンドを使用します。

整合性ストリームは、ボリューム全体・フォルダ単位・ファイル単位のいずれでも有効化/無効化を設定することができます。

整合性ストリームの有効化/無効化と確認

# Eドライブ全体で有効化
Set-FileIntegrity E: -Enable $True
# F:\Docsフォルダ配下を有効化
Set-FileIntegrity F:\Docs\ -Enable $True
# F:\Secret\Movie.mp4ファイルのみで有効化
Set-FileIntegrity F:\Secret\Movie.mp4 -Enable $True

# 確認
Get-FileIntegrity -FileName 'F:\Secret\Movie.mp4'
Get-ChildItem -Recurse F:\Docs\ | Get-FileIntegrity

また、「Data Integrity Scan」と呼ばれるタスクがタスクスケジューラに登録されており、このタスクで定期的に全データの読み取りチェックとエラー修正を行っています。
しかし、Windows10ではデフォルトでタスクの実行トリガーが無効になっているため、利用する場合は有効化が必要です。

Tip

タスクスケジューラから、タスクスケジューラライブラリ→Microsoft→Windows→Data Integrity Scan内のタスク「Data Integrity Scan」をダブルクリックし、トリガータブで各トリガーの編集画面から「有効」にチェック

ミラーリングによって高速化されたパリティ(Mirror-accelerated Parity)

「ミラーリングによって高速化されたパリティ」とは、記憶域スペースダイレクトの機能で、ミラーとパリティの異なるの回復性を備えたボリュームを作成できる機能です。
これは、記憶域スペースダイレクト、記憶域階層、およびReFSといった機能を組み合わせて実現しています。 Windows Server 2016 Datacenter/Windows Server 2019 Datacenterでサポートされています。

詳細については、下記の記事を参照してください。
ミラーリングによって高速化されたパリティ - Microsoft Docs

ミラーとパリティのメリット・デメリット

ミラーとパリティ、それぞれの回復性には下記のようなメリット・デメリットがあります。

回復性の種類 メリット デメリット
ミラー 書き込み性能が高い ストレージ容量の利用効率が悪い
パリティ ストレージ容量の利用効率が良い 書き込み毎にパリティを再計算するため
ランダム書き込み性能が低い

上記のデメリットを補うために、ミラーとパリティの両方の回復性を持たせて、ストレージ容量の高利用効率と高ランダム書き込み性能を両立する機能が「ミラーリングによって高速化されたパリティ」です。

おことわり

本来、「ミラーリングによって高速化されたパリティ」を利用するには、Windows Server2016 Datacenter以降のOSである必要がありますが、今回はWindows10 Pro for Workstationで構築してみました。
公式にはサポートされていない環境ですので、将来のアップデートなどで正常に利用できなくなる可能性が有ることを、事前にお断りしておきます。

ディスク構築

使用したハードウェア仕様は下記の通りです。

CPU Intel Pentium Gold G4500@3.5GHz
Memory DDR4-2400 32GBGB (Dual Channel)
SSD AGI 256G16AI198 256GB x2 (PCI-E 3.0 x4)
HDD WDC WD60EZRZ 6TB x6 (5400rpm SATA) +
ST10000VN0004 10TB x7 (7200rpm SATA)
OS Windows 10 Pro for Workstations

下記の図の様な構成の仮想ディスクを構築します。

図:

では、実際にSSD:200GB + HDD:32TB の仮想ディスクを作成してみます。

# SSD階層を作成
$SSDTier = New-StorageTier -StoragePoolFriendlyName '記憶域プール' -FriendlyName 'SSD階層' -MediaType SSD -ResiliencySettingName Mirror -ProvisioningType Fixed
# HDD階層を作成 NumberOfColumnsはHDDの本数に合わせて'6'を設定
$HDDTier = New-StorageTier -StoragePoolFriendlyName '記憶域プール' -FriendlyName 'HDD階層' -MediaType HDD -ResiliencySettingName Parity -ProvisioningType Fixed -NumberOfColumns 6

# 仮想ディスク、ボリュームを作成 ドライブレターは'Z'を割当て
New-Volume -FriendlyName 'Disk' -DriveLetter Z -FileSystem ReFS -WriteCacheSize 16GB -StorageTiers $SSDTier,$HDDTier -StorageTierSizes 214748364800,35184372088832

# 整合性ストリームをON
Set-FileIntegrity Z: -Enable $true

ベンチマーク

とりあえず、エラー無く作成できましたので、下記の条件でベンチマークを取ってみます。

  • 使用ソフト: CrystalDiskMark 6.0.3
  • 試行回数: 5回
  • ReFSの場合、整合性ストリームON
  • WriteCache: 16GB

記憶域階層ファイル
システム
Sequential   Random (MB/s)
ReadWriteReadWrite
なしReFS 850.4 54.64 5.1124.63
NTFS 718.3 499.8 4.52 0.95
ありReFS 520.5 780.2 3.49 84.6
NTFS3192.1 734.1258.896.40

ミラー階層とパリティ階層の両方を含んだ仮想ディスクで、NTFSのボリュームは作成できないのかと思っていましたが、作成できてしまいました。
結果として、予期していませんでしたが、ランダム書き込みで一番高パフォーマンスなのは「記憶域階層を利用したNTFS」のパターンとなりました。

考察

書き込みについては有意な差が見られ、記憶域階層を利用した方が高パフォーマンスになりました。
また読み込みについては、記憶域階層を利用したReFSが一番パフォーマンスが低くなりました。 これは「ミラーリングによって高速化されたパリティ」が、記憶域スペースダイレクトでの利用を前提としており、 記憶域スペースダイレクトの読み込みキャッシュ機能を利用して性能向上させる設計なのかと思います。

なお、ここまで書いておきながらなのですが、今回のベンチマーク結果は正式にサポートされた環境での測定されたものではないため「ミラーリングによって高速化されたパリティ」が正しく構築できた結果なのかは不明です。

余談

ちなみに、下記を試してみましたが、Not Supportedエラーが発生しました。

  • 記憶域階層作成時のProvisioningTypeをThin(シンプロビジョニング)に設定
    恐らく対応していないものと思います。
    もし、実運用上で容量の拡張が必要となった場合には、ディスクを追加後に仮想ディスクとファイルシステムの拡張という運用になるかと思います。
  • 仮想ディスク作成時にReadCacheSizeを設定
    これは記憶域スペースダイレクトでないと利用できないようです。

仮想ディスクの拡張

運用中に仮想ディスクの容量が不足した場合、物理ディスクを追加することで仮想ディスクのサイズを拡張することができます。

パターン1: シンプロビジョニングの仮想ディスクの場合

あらかじめ、仮想ディスクサイズに余裕をもってシンプロビジョニングのディスクにしている場合は、記憶域プールに物理ディスクを追加するだけです。

# 物理ディスクを記憶域プールに追加
Get-PhysicalDisk -CanPool $true | Add-PhysicalDisk -StoragePoolFriendlyName 記憶域プール

パターン2: 記憶域階層を使用しない、固定サイズ仮想ディスクの場合

記憶域プールに物理ディスクを追加後、仮想ディスクサイズとパーティションサイズを拡張します。

# 物理ディスクを記憶域プールに追加
Get-PhysicalDisk -CanPool $true | Add-PhysicalDisk -StoragePoolFriendlyName 記憶域プール

# 仮想ディスクサイズを4TBに拡張
$virtialDisk = Get-VirtualDisk 仮想ディスク
$virtialDisk | Resize-VirtualDisk -Size 4TB

# パーティションサイズを拡張
$partition = $virtialDisk | Get-Disk | Get-Partition | Where-Object Type -eq Basic
$partition | Resize-Partition -Size ($partition | Get-PartitionSupportedSize).SizeMax

パターン3: 記憶域階層を使用している場合

記憶域プールに物理ディスクを追加後、対象の記憶域階層のサイズとパーティションサイズを拡張します。

# 物理ディスクを記憶域プールに追加
Get-PhysicalDisk -CanPool $true | Add-PhysicalDisk -StoragePoolFriendlyName 記憶域プール

# HDD階層のサイズを32TBに拡張
$virtialDisk = Get-VirtualDisk 仮想ディスク
$virtialDisk | Get-StorageTier -MediaType HDD | Resize-StorageTier -Size 32TB 

# パーティションサイズを拡張
$partition = $virtialDisk | Get-Disk | Get-Partition | Where-Object Type -eq Basic
$partition | Resize-Partition -Size ($partition | Get-PartitionSupportedSize).SizeMax