HDFSイレイジャーコーディング

目的

レプリケーションはコストがかかります。HDFSのデフォルトの3xレプリケーションスキームでは、ストレージ容量とその他のリソース(例:ネットワーク帯域幅)に200%のオーバーヘッドがあります。しかし、比較的I/Oアクティビティの低いウォームデータとコールドデータの場合、通常の運用中は追加のブロックレプリカにアクセスすることはめったにありませんが、それでも最初のレプリカと同じ量の資源を消費します。

そのため、ストレージ容量を大幅に削減しながら、同じレベルのフォールトトレランスを提供するイレイジャーコーディング(EC)をレプリケーションの代わりに使用することが自然な改善策となります。一般的なイレイジャーコーディング(EC)の設定では、ストレージオーバーヘッドは50%以下です。ECファイルのレプリケーションファクターは無意味です。常に1であり、-setrepコマンドでは変更できません。

背景

ストレージシステムにおいて、ECの最も注目すべき用途はRedundant Array of Inexpensive Disks(RAID)です。RAIDはストライピングによってECを実装し、論理的に連続したデータ(ファイルなど)をより小さな単位(ビット、バイト、ブロックなど)に分割し、連続した単位を異なるディスクに格納します。このガイドの残りの部分では、このストライピング分散の単位をストライピングセル(またはセル)と呼びます。元のデータセルの各ストライプに対して、特定数のパリティセルが計算され格納されます。このプロセスをエンコーディングと呼びます。任意のストライピングセルのエラーは、生存データとパリティセルに基づいてデコーディング計算によって回復できます。

HDFSにECを統合することで、従来のレプリケーションベースのHDFS展開と同様のデータ耐久性を維持しながら、ストレージ効率を向上させることができます。例として、6個のブロックを持つ3xレプリケートされたファイルは、6*3 = 18個のディスク容量を消費します。しかし、EC(6データ、3パリティ)展開では、9個のディスク容量しか消費しません。

アーキテクチャ

ECのコンテキストでは、ストライピングにはいくつかの重要な利点があります。まず、オンラインEC(EC形式でデータをすぐに書き込む)を可能にし、変換フェーズを回避し、ストレージ容量をすぐに節約できます。オンラインECは、複数のディスクスピンドルを並列して活用することで、シーケンシャルI/Oパフォーマンスも向上させます。これは、ハイエンドネットワークを備えたクラスタでは特に望ましいものです。第二に、小さなファイルを複数のDataNodeに自然に分散し、複数のファイルを単一のコーディンググループにバンドルする必要性を排除します。これにより、フェデレーションされた名前空間間の削除、クォータレポート、移行などのファイル操作が大幅に簡素化されます。

一般的なHDFSクラスタでは、小さなファイルが総ストレージ消費量の3/4以上を占める場合があります。小さなファイルをより適切にサポートするために、この最初の作業フェーズでは、HDFSはストライピングによるECをサポートしています。将来的には、HDFSは連続したECレイアウトもサポートする予定です。詳細については、設計ドキュメントとHDFS-7285に関する議論を参照してください。

  • NameNode拡張機能 - ストライプ化されたHDFSファイルは、論理的にはブロックグループで構成されており、それぞれに特定数の内部ブロックが含まれています。これらの追加ブロックによるNameNodeメモリ消費を削減するために、新しい階層型ブロックネーミングプロトコルが導入されました。ブロックグループのIDは、その内部ブロックのいずれかのIDから推測できます。これにより、ブロックではなくブロックグループレベルで管理できます。

  • クライアント拡張機能 - クライアントの読み取りと書き込みパスは、ブロックグループ内の複数の内部ブロックを並列に処理するように拡張されました。出力/書き込みパスでは、DFSStripedOutputStreamは、現在のブロックグループ内の内部ブロックを格納する各DataNodeごとに、データストリーマーのセットを管理します。ストリーマーはほとんど非同期的に動作します。コーディネーターは、現在のブロックグループの終了、新しいブロックグループの割り当てなど、ブロックグループ全体の操作を担当します。入力/読み取りパスでは、DFSStripedInputStreamは、要求されたデータの論理的なバイト範囲を、DataNodeに格納されている内部ブロックへの範囲に変換します。次に、読み取り要求を並列で発行します。障害が発生した場合、デコーディングのために追加の読み取り要求を発行します。

  • DataNode拡張機能 - DataNodeは、障害が発生したイレイジャーコード化ブロックのバックグラウンドリカバリのために、追加のErasureCodingWorker(ECWorker)タスクを実行します。障害が発生したECブロックはNameNodeによって検出され、その後、リカバリ作業を行うDataNodeが選択されます。リカバリタスクは、ハートビート応答として渡されます。このプロセスは、レプリケートされたブロックが障害時に再レプリケートされる方法に似ています。再構築は3つの主要なタスクを実行します。

    1. ソースノードからのデータの読み取り:入力データは、専用のThread Poolを使用してソースノードから並列に読み取られます。ECポリシーに基づいて、すべてのソースターゲットへの読み取り要求をスケジュールし、再構築に必要な最小限の入力ブロックのみを読み取ります。

    2. データのデコードと出力データの生成:新しいデータブロックとパリティブロックが入力データからデコードされます。すべての欠損データブロックとパリティブロックがまとめてデコードされます。

    3. 生成されたデータブロックをターゲットノードに転送する:デコードが完了すると、リカバリされたブロックがターゲットDataNodeに転送されます。

  • イレイジャーコーディングポリシー 異なるワークロードに対応するために、HDFSクラスタ内のファイルとディレクトリで、異なるレプリケーションとイレイジャーコーディングポリシーを使用できます。イレイジャーコーディングポリシーは、ファイルのエンコード/デコード方法をカプセル化します。各ポリシーは、次の情報で定義されます。

    1. ECスキーム:これには、ECグループ内のデータブロックとパリティブロックの数(例:6+3)、およびコーデックアルゴリズム(例:リードソロモン、XOR)が含まれます。

    2. ストライピングセルのサイズ。これは、バッファサイズやエンコーディング作業を含む、ストライプ化された読み取りと書き込みの粒度を決定します。

    ポリシーは、コーデック-データブロック数-パリティブロック数-セルサイズという名前で付けられます。現在、5つの組み込みポリシーがサポートされています:RS-3-2-1024kRS-6-3-1024kRS-10-4-1024kRS-LEGACY-6-3-1024kXOR-2-1-1024k

    デフォルトのREPLICATIONスキームもサポートされています。これはディレクトリに対してのみ設定でき、親のイレイジャーコーディングポリシーを継承する代わりに、ディレクトリで3xレプリケーションスキームを採用するように強制します。このポリシーにより、3xレプリケーションスキームのディレクトリとイレイジャーコーディングディレクトリをインターリーブすることが可能になります。

    REPLICATIONは常に有効です。すべてのECポリシーの中で、RS(6,3)がデフォルトで有効になっています。

    HDFSストレージポリシーと同様に、イレイジャーコーディングポリシーはディレクトリに設定されます。ファイルが作成されると、その最も近い親ディレクトリのECポリシーを継承します。

    ディレクトリレベルのECポリシーは、ディレクトリ内に作成された新しいファイルのみに影響します。ファイルが作成されると、そのイレイジャーコーディングポリシーは照会できますが、変更できません。イレイジャーコード化されたファイルを異なるECポリシーを持つディレクトリに名前変更した場合、ファイルは既存のECポリシーを保持します。ファイルを異なるECポリシーに変換するには、データの書き換えが必要です。そのためには、名前変更ではなく、ファイルをコピー(例:distcpを使用)してください。

    ユーザーはXMLファイルを使用して独自のECポリシーを定義できます。このファイルには、次の3つの部分が必要です。

    1. layoutversion:これは、ECポリシーXMLファイル形式のバージョンを示します。

    2. schemas:これには、ユーザー定義のすべてのECスキームが含まれています。

    3. policies:これには、ユーザー定義のすべてのECポリシーが含まれており、各ポリシーはスキームIDとストライピングセルのサイズ(cellsize)で構成されます。

    ユーザーが参照できるサンプルECポリシーXMLファイルuser_ec_policies.xml.templateは、Hadoopのconfディレクトリにあります。

  • Intel ISA-L Intel ISA-Lは、Intel Intelligent Storage Acceleration Libraryの略です。ISA-Lは、ストレージアプリケーション向けに設計された最適化された低レベル関数のオープンソースコレクションです。これには、Intel AVXおよびAVX2命令セット用に最適化された高速ブロックリードソロモン型イレイジャーコードが含まれています。HDFSイレイジャーコーディングは、ISA-Lを活用して、エンコーディングとデコーディングの計算を高速化できます。ISA-Lは、LinuxやWindowsなど、主要なオペレーティングシステムのほとんどをサポートしています。ISA-Lはデフォルトでは有効になっていません。ISA-Lを有効にする方法については、以下の手順を参照してください。

導入

クラスタとハードウェア構成

イレイジャーコーディングは、CPUとネットワークに関してクラスタに追加の要求を課します。

エンコーディングとデコーディングの作業は、HDFSクライアントとDataNodeの両方で追加のCPUを消費します。

イレイジャーコーディングには、構成されたECストライプ幅と同じ数のDataNodeがクラスタに最低限必要です。ECポリシーRS(6,3)の場合、これは最低9個のDataNodeを意味します。

消去符号化ファイルは、ラック障害耐性を確保するため、ラック全体に分散されます。つまり、ストライプファイルの読み書きでは、ほとんどの操作がラック外で行われます。そのため、ネットワークのバイセクション帯域幅は非常に重要です。

ラック障害耐性のためには、平均して各ラックが保持するブロック数がECパリティブロック数以下になるように、十分な数のラックを用意することが重要です。これを計算する式は、(データブロック数 + パリティブロック数) / パリティブロック数(切り上げ)となります。ECポリシーRS(6,3)の場合、最小で3つのラック((6 + 3) / 3 = 3で計算)が必要であり、計画されたおよび計画外の停止を処理するには、理想的には9つ以上のラックが必要です。パリティセルの数よりも少ない数のラックを持つクラスタでは、HDFSはラック障害耐性を維持できませんが、ノードレベルの障害耐性を維持するために、ストライプファイルを複数のノードに分散しようとします。このため、DataNode数の同様なラックを設定することをお勧めします。

設定キー

デフォルトでは、dfs.namenode.ec.system.default.policyで定義されているものを除き、すべての組み込み消去符号化ポリシーは無効になっています。これはデフォルトで有効になっています。クラスタ管理者は、クラスタのサイズと必要なフォールトトレランス特性に基づいて、hdfs ec [-enablePolicy -policy <policyName>]コマンドを使用してポリシーのセットを有効にすることができます。たとえば、9つのラックを持つクラスタでは、RS-10-4-1024kのようなポリシーはラックレベルのフォールトトレランスを維持せず、RS-6-3-1024kまたはRS-3-2-1024kの方が適切かもしれません。管理者がノードレベルのフォールトトレランスのみを気にする場合、クラスタに少なくとも14個のDataNodeがあれば、RS-10-4-1024kでも適切です。

システムデフォルトのECポリシーは、’dfs.namenode.ec.system.default.policy’設定で構成できます。この設定により、’–setPolicy’コマンドの引数としてポリシー名が渡されない場合、デフォルトのECポリシーが使用されます。

デフォルトでは、’dfs.namenode.ec.system.default.policy’は“RS-6-3-1024k”です。

リードソロモンとXORのコーデック実装は、次のクライアントとDataNodeの設定キーで構成できます。デフォルトのRSコーデックにはio.erasurecode.codec.rs.rawcoders、レガシーRSコーデックにはio.erasurecode.codec.rs-legacy.rawcoders、XORコーデックにはio.erasurecode.codec.xor.rawcodersです。ユーザーは、io.erasurecode.codec.self-defined-codec.rawcodersのような設定キーを使用して、独自定義のコーデックを構成することもできます。これらのキーの値は、フォールバックメカニズムを備えたコーダー名のリストです。これらのコーデックファクトリは、設定値で指定された順序でロードされ、コーデックが正常にロードされるまで続行されます。デフォルトのRSおよびXORコーデック設定は、純粋なJava実装よりもネイティブ実装を優先します。RS-LEGACYネイティブコーデックの実装はないため、デフォルトは純粋なJava実装のみです。これらのコーデックはすべて純粋なJavaで実装されています。デフォルトのRSコーデックには、Intel ISA-Lライブラリを活用してコーデックのパフォーマンスを向上させるネイティブ実装もあります。XORコーデックについても、Intel ISA-Lライブラリを活用してコーデックのパフォーマンスを向上させるネイティブ実装がサポートされています。「Intel ISA-Lの有効化」セクションを参照して、詳細情報を確認してください。RSレガシーのデフォルト実装は純粋なJavaであり、デフォルトのRSとXORのデフォルト実装はIntel ISA-Lライブラリを使用したネイティブ実装です。

DataNodeでの消去符号化バックグラウンドリカバリ作業は、次の設定パラメータでも調整できます。

  1. dfs.datanode.ec.reconstruction.stripedread.timeout.millis - ストライプ読み込みのタイムアウト。デフォルト値は5000ミリ秒です。
  2. dfs.datanode.ec.reconstruction.stripedread.buffer.size - リーダーサービスのバッファサイズ。デフォルト値は64KBです。
  3. dfs.datanode.ec.reconstruction.threads - DataNodeがバックグラウンド再構築作業に使用しているスレッド数。デフォルト値は8スレッドです。
  4. dfs.datanode.ec.reconstruction.xmits.weight - レプリケートされたブロックリカバリと比較した、ECバックグラウンドリカバリタスクで使用されるxmitsの相対的な重み。デフォルト値は0.5です。ECリカバリタスクの重みの計算を無効にするために0に設定します。つまり、ECタスクのxmitsは常に1になります。消去符号化リカバリタスクのxmitsは、読み込みストリーム数と書き込みストリーム数の最大値として計算されます。たとえば、ECリカバリタスクが6ノードから読み取り、2ノードに書き込む必要がある場合、xmitsはmax(6, 2) * 0.5 = 3となります。レプリケートされたファイルのリカバリタスクは常に1 xmitとしてカウントされます。NameNodeは、レプリケートされたファイルとECファイルからのxmitsを組み合わせたDataNode上の合計xmitsInProgressからdfs.namenode.replication.max-streamsを引いた値を使用して、このDataNodeへのリカバリタスクのスケジュールを決定します。

Intel ISA-Lの有効化

HDFSのデフォルトRSコーデックのネイティブ実装は、Intel ISA-Lライブラリを活用してエンコードとデコードの計算を高速化します。Intel ISA-Lを有効化して使用するには、3つの手順があります。

  1. ISA-Lライブラリをビルドします。詳細については、公式サイト「https://github.com/01org/isa-l/」を参照してください。
  2. ISA-Lサポート付きでHadoopをビルドします。ソースコードの(BUILDING.txt)にある「Hadoopのビルド手順」の「Intel ISA-Lビルドオプション」セクションを参照してください。
  3. -Dbundle.isalを使用して、isal.libディレクトリのコンテンツを最終的なtarファイルにコピーします。tarファイルを使用してHadoopを展開します。HDFSクライアントとDataNodeでISA-Lが使用可能であることを確認してください。

HadoopによってISA-Lが正しく検出されていることを確認するには、hadoop checknativeコマンドを実行します。

管理コマンド

HDFSは、消去符号化に関連する管理コマンドを実行するためのecサブコマンドを提供します。

   hdfs ec [generic options]
     [-setPolicy -path <path> [-policy <policyName>] [-replicate]]
     [-getPolicy -path <path>]
     [-unsetPolicy -path <path>]
     [-listPolicies]
     [-addPolicies -policyFile <file>]
     [-listCodecs]
     [-enablePolicy -policy <policyName>]
     [-disablePolicy -policy <policyName>]
     [-removePolicy -policy <policyName>]
     [-verifyClusterSetup -policy <policyName>...<policyName>]
     [-help [cmd ...]]

各コマンドの詳細を以下に示します。

  • [-setPolicy -path <path> [-policy <policyName>] [-replicate]]

    指定されたパスにあるディレクトリに消去符号化ポリシーを設定します。

    path: HDFS内のディレクトリ。これは必須パラメータです。ポリシーの設定は、新しく作成されたファイルのみに影響し、既存のファイルには影響しません。

    policyName: このディレクトリ以下のファイルに使用される消去符号化ポリシー。’dfs.namenode.ec.system.default.policy’設定が設定されている場合は、このパラメータを省略できます。パスのECポリシーは、設定のデフォルト値に設定されます。

    -replicateは、ディレクトリにデフォルトのREPLICATIONスキームを適用し、ディレクトリに3xレプリケーションスキームを強制的に採用させます。

    -replicate-policy <policyName>はオプションの引数です。同時に指定することはできません。

  • [-getPolicy -path <path>]

    指定されたパスにあるファイルまたはディレクトリの消去符号化ポリシーの詳細を取得します。

  • [-unsetPolicy -path <path>]

    ディレクトリで以前のsetPolicy呼び出しによって設定された消去符号化ポリシーの設定を解除します。ディレクトリが祖先ディレクトリから消去符号化ポリシーを継承している場合、unsetPolicyはノーオペレーションです。明示的なポリシーが設定されていないディレクトリでポリシーの設定を解除しても、エラーは返されません。

  • [-listPolicies]

    HDFSに登録されているすべての(有効、無効、削除済み)消去符号化ポリシーをリストします。setPolicyコマンドで使用できるのは、有効なポリシーのみです。

  • [-addPolicies -policyFile <file>]

    ユーザー定義の消去符号化ポリシーのリストを追加します。例としてpolicyファイルについては、etc/hadoop/user_ec_policies.xml.templateを参照してください。最大セルサイズは、プロパティ’dfs.namenode.ec.policies.max.cellsize’で定義され、デフォルト値は4MBです。現在、HDFSでは合計64個のポリシーを追加でき、追加されたポリシーIDは64から127の範囲です。64個のポリシーが既に追加されている場合は、ポリシーの追加は失敗します。

  • [-listCodecs]

    システムでサポートされている消去符号化コーデックとコーダーのリストを取得します。コーダーはコーデックの実装です。コーデックには異なる実装、つまり異なるコーダーを持つことができます。コーデックのコーダーは、フォールバック順序でリストされます。

  • [-removePolicy -policy <policyName>]

    ユーザー定義の消去符号化ポリシーを削除します。

  • [-enablePolicy -policy <policyName>]

    消去符号化ポリシーを有効にします。

  • [-disablePolicy -policy <policyName>]

    消去符号化ポリシーを無効にします。

  • [-verifyClusterSetup -policy <policyName>...<policyName>]

    クラスタの設定ですべての有効な消去符号化ポリシーをサポートできるかどうかを確認します。オプションのパラメータ-policyが指定されている場合、クラスタの設定で指定されたポリシーをサポートできるかどうかを確認します。

制限事項

hflushhsyncconcatsetReplicationtruncateappendなどの一部のHDFS操作は、技術的な課題が大きいため、消去符号化ファイルではサポートされていません。

  • 消去符号化ファイルに対するappend()truncate()は、IOExceptionをスローします。
  • ファイルが異なる消去符号化ポリシーを持つファイルやレプリケートされたファイルと混在している場合、concat()IOExceptionをスローします。
  • setReplication()は、消去符号化ファイルではノーオペレーションです。
  • DFSStripedOutputStreamに対するhflush()hsync()はノーオペレーションです。したがって、消去符号化ファイルに対してhflush()またはhsync()を呼び出しても、データの永続性が保証されるわけではありません。

クライアントはStreamCapabilities APIを使用して、OutputStreamhflush()hsync()をサポートするかどうかを照会できます。クライアントがhflush()hsync()によるデータ永続性を求める場合、現在の解決策は、消去符号化されていないディレクトリに通常の3xレプリケーションファイルとしてそのようなファイルを作成するか、FSDataOutputStreamBuilder#replicate() APIを使用して消去符号化ディレクトリに3xレプリケーションファイルを作成することです。