RAIDを導入する前に考えること


# はじめに

実体験から学ぶことは多いわけで、ここではZFSのRAIDZで少々失敗したお話。ZFSでの話ではあるが、特にZFSに依存した話ではなく同様のハードウェアでRAID 5や6を構成すれば同じ問題が起きるはずなので、参考になれば幸いである。

# 事の起こり、RAIDZ2の導入

3年ぐらい前の話になるが、会社でUSB 3.0接続でHDDを5台入る筐体に1TB HDDを積んだものを用意してもらった。つまり総容量は5TBである。この箱のインターフェースにはUSB 3.0の他にeSATAも用意されていたが、サーバー側にはeSATAは無いためUSB 3.0で接続した。

当時の要望として容量の面では1TBもあれば用が足りるため、5台あればRAIDZ2を構成しても3TB確保できることから、RAIDZ2として構成したのであった。

# RAIDZ

ZFSではRAIDを構成する場合RAIDZという名称で、一般的なRAIDに当てはめると、RAIDZがRAID 5、RAIDZ2がRAID 6に相当する。ここで少しだけRAID 5、6について簡単に説明する。

RAID 5 or 6ではディスクを一定サイズ(話を単純にするために1MBとする)のブロックで分割し、ディスクの台数分のブロックをまとめ(5台だと5MB)、パリティを割り当てて管理する。RAID 5がシングルパリティ、6がダブルパリティであるため、5台のディスクだとRAID 5ではデータ分が4MB、パリティ分が1MB、RAID 6ではデータ分が3MB、パリティが2MBとなる。この管理単位を1MBづつ各ディスクに分散して配置することで、ディスクシステムの信頼性と冗長性を確保する。具体的にはRAID 6であれば、ディスクが1台壊れてもデータの整合性が保証でき、2台壊れてもデータの継続性が保証できる。

しかしながら一般的なRAID 5や6には、管理サイズより小さなサイズの書き込みには大きなペナルティが発生する。例えば上記構成のRAID 6で1MB分のデータを更新するためには、一旦管理単位のデータ3MB、パリティ2MB分のデータを読み出し、データの整合性を確認後に1MB分更新したデータを改めて書き戻す必要がある。つまり1MBの書き込みのために、5MBのデータの読み込みと同容量のデータの書き戻しが必要になるのである。多くの場合書き込みはOSのバッファによってアプリ側からのペナルティは小さいが、データの書き込みのために読み込みが必要になるのはパフォーマンスの面からは無視できないものとなる。実際の市販の多くのRAIDシステムでは、内部に大容量のバッファメモリを用意することでこのデータ書き込み時のパフォーマンス低下の問題を回避している。

ZFSでのRAIDZでは、データの管理単位を一定の固定サイズではなく可変サイズとしてコピー・オン・ライトで動作するため、データの書き込みの際に既存データの読み出しの必要が無い。このため、RAIDZでは、データの書き込みに大きなペナルティは発生せず、特別のバッファメモリ等を利用しなくても実用上十分な書き込み速度が得られる。

# データの読み出しが遅い！

ZFSの経験はそれなりにあるものの、RAIDZ2を利用するのはこのシステムが初めてであった。実際にRAIDZ2を使い始めてすぐに気づいたのは、一般的なディスクに比べてデータの読み出しに時間がかかるということである。

考えてみれば当然の話で、5台のディスクでRAIDZ2であれば、3MB分のデータを読み込むには、データ分に加えてパリティ分2MBを読み出す必要がある。つまり単純に1台のディスクから3MBのデータを読み出すのに比較し、5/3(1.67)倍の読み出し時間が必要になる(パリティの計算時間はディスクアクセス時間に比べると無視できる)。

5台のディスクそれぞれを並行で同時に読み出すことが出来れば、ここまで大きなペナルティにはならないのかもしれないが、USB接続のディスクでは1台づつ順番に読み出しているようである(観察に基づく推測なので、違っているようでればコメントで教えて欲しい)。SATAやSAS接続のディスクであればまた違った動作になる可能性はある。

# USB 3.0 接続のディスクが遅い！

データの読み出しが遅いことは把握していたものの、一旦運用を始めたサーバーでは簡単に構成変更はできず、そのまま使い続けてきた。そして3年近く経過した半年ほど前の話になるが、ディスクはそのままでサーバー側を交換することになり、新たなサーバにOSをインストールして、今まで使っていたディスクをそのまま接続した。

以前からサーバーではMacのタイムマシンバックアップを行っていたのだが、新サーバーにはSATAで1TBのディスクが内蔵されていたので、ある日試しに内蔵ディスクにタイムマシンバックアップを行ってみてその結果に愕然とした。1回あたりのタイムマシンのバックアップ時間が今までは30分～1時間、あるいはもっとかかっていたものが、ほんの数分程度(大部分が10分以下)で済むようになったのである。

タイムマシンのバックアップの挙動を観測すると、実際のバックアップデータの書き込み前に前回のバックアップとの比較と思われる大量の比較的小さなデータの読み出しが発生している。ここでRAIDでのディスク読み出しの挙動を考えてみると、5台構成のRAIDZ2(RAID 6)であればどんなに小さなデータを読み出す場合であっても5 台のディスクからの読み出しが必要となるのは明らかである。これに対して1台のディスクであれば、読み出しは1台分済む。

実際のデータの読み出しでは、ディスクに対して読み込みのコマンドの発行と読み込みデータの取り込みが必要である。コマンドの発行に必要な時間と実際にデータ転送が始まるまでの時間をA、データの転送に必要な時間をBすると、データの読み込みに必要な時間は次のようになる。

|  |  |
|:-:|:-:|
| シングルディスク  |A + B    |
| 5台構成のRAIDZ2 (RAID 6)  | (A' * 5) + B  |

これだけでも明らかに5台構成のRAIDは不利であるが、さらにUSB 3.0とSATAでは A と A' の時間には大きな差があるように思える(機会があれば計測したい)。
USB 3.0のインターフェースの速度は 5Gbpsであり、SATAの6Gbpsと比較すると遅いとは言え、もそこまで大きな差ではない。しかしUSB接続のHDDの場合、HDD自体のインターフェースはSATAであるため、内部でUSB⇔SATAのインターフェース変換をおこなっている。そのせいかどうまでは不明だが、USB経由のストレージアクセスのレイテンシは、SATAのレイテンシに比べて相当大きいのではないかと推測する。

# 結局どうしたの？

これらの現実を把握したこともあり、タイムマシンバックアップはサーバーの内蔵ディスクだけで行うように変更した。それと共にRAIDZ2のディスク箱のデータを整理し、容量的にも問題ないので、4台のディスクを組み合わせてRAID 1+0に構成変更を行った。ディスクが1台余るのでスペアディスクとして割り当てた。以前のRAIDZ2に比べると、読み書きのパフォーマンスは一回りよくなったようである。

# まとめ

長文となってしまったが結局言いたいことは、こんなところだろうか。

- USB接続のハードディスクでRAIDによる冗長性を確保する場合は、5や6は避けRAID 1つまりミラーで構成するのが得策である

あくまでもここではUSB接続のハードディスクでの話である。知人の話を聞く限りSATAやSAS接続のハードディスクであればこれよりはパフォーマンスは良さそうだが、自分では試せていない。

追記 (2021-12-17)
実際に違いを計測できたので、「[ストレージインターフェースにおけるSATAとUSBの性能差](https://qiita.com/belgianbeer/items/9f963d6b33fd4124b45f)」にまとめました。