ZFS におけるエンド・ツー・エンドのデータ整合性

ブロックの読み込み要求をした場合、前回そのブロックに書き込んだときと同じデータが返ってこなければなりません。どんなファイルシステムでも、その役割は結局ここに行き着きます。ディスクがオフラインであるとか、データが破損したとか、改ざんされたなどの理由で、もし同じデータを返せないのなら、それを検出してエラーを返さなければなりません。

驚くべきことに、ほとんどのファイルシステムがこの課題をクリアできません。そのようなファイルシステムでは、エラーの検出と報告を下位のハードウェアに頼っています。もしディスクが何の報告もせずただ誤ったデータだけを返した場合、標準的なファイルシステムはそれを検出することすらできません。

たとえすべてのディスクが完璧に動作すると仮定できたとしても、入出力経路上のデータはまだ安全ではありません。コントローラのバグやDMA パリティーエラーなどがありえます。ユーザーにわかるのは、プラッタから読み取る瞬間までデータが完全だったというところまでです。データを小包に例えると、USP が「集荷の際にお荷物に損傷がなかったことを保証いたします」と言うようなものです。ユーザーが求めている信頼性とは少々異なります。

転送中のデータ破損は、単なる学問的な興味の対象ではありません。電源供給の誤切断のようなありふれた原因で、データのサイレント破損が起きます。

高価なストレージアレイをオプションで購入しても、問題の解決にはなりません。I/O パスが脆弱なままで、しかも経路が延びてしまいます。プラッタから読み取ったあと、ハードウェアやファームウェアにどのようなバグがあってもデータが無事であることを、ストレージアレイが保証しなければなりません。

もし SAN を使っているなら、ディスクのファームウェア技術者が設計したネットワークを使っていることになります。ご愁傷様。

どうすればよいのでしょうか。すべてのディスクブロックについてチェックサムを保存しておくという方法があります。近年のディスクドライブは、通常の 512 バイトよりもわずかに大きいセクターサイズ (520 か 528 バイトが一般的) でフォーマットして、余分に確保した領域にブロックのチェックサムを保存することができます。しかし、このチェックサムを有効活用するのは思ったほど簡単ではありません。チェックサムの有効性は、どこにチェックサムを保存するかと、いつチェックサムの検証を行うかに、恐ろしいほど依存しているからです。

多くのストレージアレイでは、アレイの内部でデータとチェックサムを比較します。Dell|EMC PowerVault のレポートに、すばらしい解説つきで一般的な例が掲載されています。残念ながら、これではあまり役に立ちません。データとチェックサムが同じユニットに保存されるため、書き込み成功の誤報告 (前回書き込んだはずの内容がディスクに書き込まれていない) など、よくあるファームウェアのバグを検出できません。つまり、ディスクが古いデータを返しても、チェックサムは一致します。しかも、アレイからホストまでの I/O パスは保護されないままになっています。つまりこの種のブロックチェックサムは、ストレージアレイが搭載しているディスクと比較して信頼性で劣っていないということを保証するのに適した手段になりますが、それだけなのです。

チェックサムをブロックに追加する NetApp のアプローチも似たようなものに見えますが、実はかなり違います。ほかの多くのアレイと同様に、NetApp ではドライブを 520 バイトセクターでフォーマットします。その上で、8 セクターでひとまとまりのブロックを作ります。4K のデータ (WALF ファイルシステムのブロックサイズ) と 64 バイトのチェックサムを保存可能な容量になります。WAFL がブロックを読み込むと、ほかのアレイと同様にチェックサムとデータを比較しますが、決定的な違いがあります。データが I/O パスを通過したあとに比較を行うので、プラッタで読み取られたデータブロックが経路上で破損することなくメモリに到着したかどうか検証できます。

これは大きな進歩ですが、まだ十分ではありません。ブロックレベルのチェックサムは、ブロックが同一性を保っていることを保証するのみで、それが正しいブロックであるかどうか確認できません。UPS のたとえでいうと「荷物が途中で破損しなかったことを保証しますが、お客様の荷物かどうかは保証しません」ということになります。

ここまで紹介したスキーマすべてに共通する根本的な問題は、データとそれを保護するチェックサムを分けずに保管しているという点です。

ZFS のデータ確認

エンド・ツー・エンドのデータ整合性を得るには、すべてのデータブロックが、別途保存されたチェックサムで、データがホストのメモリに到達したあとに、検証される必要があります。各ブロックが単に同一性を保っているとか、I/O パスのある時点で正しかったなどというだけでは、不十分です。私たちの目標は、ディスクの入れ間違いや dd(1) コマンド引数のミスタイプなどのヒューマンエラーも含めて、想定しうるすべての破損を検出することです。「if=」と入力しようとして「of=」とタイプしてしまったことはありませんか。

ZFS のストレージプールはブロックをツリー状に集めただけのものです。ZFS は、各ブロックのチェックサムを、そのブロック自体と同じ場所ではなく、親ブロックのポインタに保存することで、データとチェックサムの問題を��り分けています。ツリー上のすべてのブロックが子ブロックのチェックサムを持っており、プール全体で破損の検証が可能です。(最上位ブロック (ツリーのルート) は例外で、親ブロックがありませんが、どのように処理しているかは後日投稿します。)

データとチェックサムが一致しない場合、チェックサムを保存してあるツリー上の 1 段上の階層のブロックはすでに検証が済んでいるため、ZFS はチェックサムを信頼できると判断できます。

ZFS は、このエンド・ツー・エンドのチェックサムを利用して、データのサイレント破損を検出し訂正しています。ディスクから不正なデータが返ってきた場合、ZFS がこれを検出して読み取りをリトライします。ディスクがミラーまたは RAID-Z を構成している場合、ZFS はエラーの検出と訂正の両方を行います。チェックサムと比較してどちらのコピーが正しいかを判断し、アプリケーションに正常なデータを送り、破損したコピーを訂正します。

何度も書いていますが、ZFS のエンド・ツー・エンドデータ整合性には特別なハードウェアが必要ないことに注目してください。高価なディスクやストレージアレイを購入する必要も、ディスクを 520 バイトセクターで再フォーマットする必要も、エラー訂正を有効にするためにアプリケーションの設定をする必要もありません。すべて自動で、安価なディスクでも機能します。

もう少しだけ

ZFS ストレージプールのブロックは、各ブロックが子ブロックを検証する Merkle ツリーを構成します。Merkle ツリーは、ツリーのどの部分についても、またツリー全体についても、暗号学的に強力な検証方式であることが知られています。ZFS は各ブロックに 256 ビットのチェックサムを用意しており、単純で高速な fletcher2 (デフォルト) から、速度は落ちるものの安全性の高い SHA-256 まで、チェックサムの種類を選択することができます。SHA-256 のような暗号学的ハッシュを用いる場合、最上位ブロックのチェックサムが常に、ストレージプール全体に関する最新のデジタル署名として機能します。

UPS に運送を頼むなら、どの方法が便利でしょうか。


Technorati タグ:
Comments:

Post a Comment:
Comments are closed for this entry.
About

bonwick

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today