HDFS スナップショットは、ファイルシステムの読み取り専用の特定時点のコピーです。スナップショットは、ファイルシステムのサブツリーまたはファイルシステム全体で取得できます。スナップショットの一般的なユースケースには、データのバックアップ、ユーザーエラーからの保護、および災害復旧があります。
HDFS スナップショットの実装は効率的です
スナップショットの作成は瞬時です。コストは inode 検索時間を除いて O(1) です。
追加のメモリは、スナップショットを基準とした変更が行われた場合にのみ使用されます。メモリ使用量は O(M) であり、M は変更されたファイル/ディレクトリの数です。
データノード内のブロックはコピーされません。スナップショットファイルは、ブロックリストとファイルサイズを記録します。データのコピーはありません。
スナップショットは、通常の HDFS 操作に悪影響を与えません。変更は逆時系列で記録されるため、現在のデータに直接アクセスできます。スナップショットデータは、現在のデータから変更を差し引くことによって計算されます。
ディレクトリがスナップショット可能として設定されると、そのディレクトリでスナップショットを取得できます。スナップショット可能なディレクトリは、65,536 個の同時スナップショットを収容できます。スナップショット可能なディレクトリの数に制限はありません。管理者は、任意のディレクトリをスナップショット可能に設定できます。スナップショット可能なディレクトリにスナップショットがある場合、すべてのスナップショットが削除されるまで、ディレクトリを削除または名前変更することはできません。
ネストされたスナップショット可能なディレクトリは現在許可されていません。つまり、あるディレクトリの祖先/子孫のいずれかがスナップショット可能なディレクトリである場合、そのディレクトリをスナップショット可能に設定することはできません。
スナップショット可能なディレクトリの場合、パスコンポーネント “.snapshot” は、そのスナップショットにアクセスするために使用されます。/foo
がスナップショット可能なディレクトリで、/foo/bar
が /foo
内のファイル/ディレクトリで、/foo
にスナップショット s0
があるとします。次に、パス /foo/.snapshot/s0/bar
は、/foo/bar
のスナップショットコピーを参照します。通常 API および CLI は、”.snapshot” パスで機能します。次にいくつかの例を示します。
スナップショット可能なディレクトリの下にあるすべてのスナップショットを一覧表示する
hdfs dfs -ls /foo/.snapshot
スナップショット s0
内のファイルを一覧表示する
hdfs dfs -ls /foo/.snapshot/s0
スナップショット s0
からファイルをコピーする
hdfs dfs -cp -ptopax /foo/.snapshot/s0/bar /tmp
この例では、タイムスタンプ、所有権、パーミッション、ACL、および XAttr を保持するために、preserve オプションを使用していることに注意してください。
HDFS スナップショット機能では、スナップショットを操作するために使用される新しい予約済みパス名 .snapshot
が導入されています。スナップショットをサポートしていない古いバージョンの HDFS からアップグレードする場合、予約済みパスと競合しないように、.snapshot
という名前の既存のパスを最初に名前変更または削除する必要があります。詳細については、HDFS ユーザーガイドのアップグレードセクションを参照してください。
このセクションで説明する操作には、スーパーユーザー権限が必要です。
ディレクトリのスナップショットの作成を許可します。操作が正常に完了すると、ディレクトリはスナップショット可能になります。
コマンド
hdfs dfsadmin -allowSnapshot <path>
引数
path | スナップショット可能なディレクトリのパス。 |
HdfsAdmin
の対応する Java API void allowSnapshot(Path path)
も参照してください。
ディレクトリのスナップショットの作成を禁止します。スナップショットを禁止する前に、ディレクトリのすべてのスナップショットを削除する必要があります。
コマンド
hdfs dfsadmin -disallowSnapshot <path>
引数
path | スナップショット可能なディレクトリのパス。 |
HdfsAdmin
の対応する Java API void disallowSnapshot(Path path)
も参照してください。
このセクションでは、ユーザー操作について説明します。HDFS スーパーユーザーは、個々の操作の権限要件を満たさなくても、すべての操作を実行できることに注意してください。
スナップショット可能なディレクトリのスナップショットを作成します。この操作には、スナップショット可能なディレクトリの所有者権限が必要です。
コマンド
hdfs dfs -createSnapshot <path> [<snapshotName>]
引数
path | スナップショット可能なディレクトリのパス。 |
snapshotName | スナップショット名。これはオプションの引数です。省略すると、デフォルト名が "s'yyyyMMdd-HHmmss.SSS" という形式のタイムスタンプを使用して生成されます (例: "s20130412-151029.033" )。 |
FileSystem の対応する Java API Path createSnapshot(Path path)
および Path createSnapshot(Path path, String snapshotName)
も参照してください。スナップショットパスはこれらのメソッドで返されます。
スナップショット可能なディレクトリからスナップショットを削除します。この操作には、スナップショット可能なディレクトリの所有者権限が必要です。
コマンド
hdfs dfs -deleteSnapshot <path> <snapshotName>
引数
path | スナップショット可能なディレクトリのパス。 |
snapshotName | スナップショット名。 |
FileSystem の対応する Java API void deleteSnapshot(Path path, String snapshotName)
も参照してください。
スナップショットの名前を変更します。この操作には、スナップショット可能なディレクトリの所有者権限が必要です。
コマンド
hdfs dfs -renameSnapshot <path> <oldName> <newName>
引数
path | スナップショット可能なディレクトリのパス。 |
oldName | 古いスナップショット名。 |
newName | 新しいスナップショット名。 |
FileSystem の対応する Java API void renameSnapshot(Path path, String oldName, String newName)
も参照してください。
現在のユーザーにスナップショットを取得する権限があるすべてのスナップショット可能なディレクトリを取得します。
コマンド
hdfs lsSnapshottableDir
引数: なし
DistributedFileSystem
の対応する Java API SnapshottableDirectoryStatus[] getSnapshottableDirectoryListing()
も参照してください。
2 つのスナップショット間の差分を取得します。この操作には、両方のスナップショット内のすべてのファイル/ディレクトリに対する読み取りアクセス権限が必要です。
コマンド
hdfs snapshotDiff <path> <fromSnapshot> <toSnapshot>
引数
path | スナップショット可能なディレクトリのパス。 |
fromSnapshot | 開始スナップショットの名前。 |
toSnapshot | 終了スナップショットの名前。 |
snapshotDiff は、2 つのスナップショット間、またはスナップショットとディレクトリの現在のステータス間の差分レポートを取得するために使用できることに注意してください。ユーザーは、現在のステータスを表すために “.” を使用できます。
結果
+ | C |
- | ファイル/ディレクトリが作成されました。 |
D | ファイル/ディレクトリが削除されました。 |
M | ファイル/ディレクトリが変更されました。 |
R
ファイル/ディレクトリの名前が変更されました。
R. /foo -> /foo2 M. /foo/bar
RENAME エントリは、ファイル/ディレクトリの名前が変更されたが、同じスナップショット可能なディレクトリの下にあることを示します。ファイル/ディレクトリがスナップショット可能なディレクトリの外部に名前変更された場合、削除されたと報告されます。スナップショット可能なディレクトリの外部から名前変更されたファイル/ディレクトリは、新しく作成されたものとして報告されます。
スナップショットの差分レポートは、同じ操作シーケンスを保証しません。たとえば、ディレクトリ “/foo” の名前を “/foo2” に変更し、ファイル “/foo2/bar” に新しいデータを追加すると、差分レポートは次のようになります。