HDFSのスナップショット

この投稿は、Hadoop Advent Calendar 2013 - Qiita [キータ] 21日目です。
今日は、HDFSのスナップショットについて書きます。

HDFSスナップショット

HDFSスナップショットは、特定の時点でのHDFSの状態を記録しておくことで、問題があった場合に容易に復旧させることができる、バックアップを容易にするという目的で、Hadoopの機能としてHadoop2.2系より提供されています。
これまでも利用者が複数のコマンド(Hadoop、OS)を組み合わせれば同じような仕組みを実現できたと思いますが、これにより統一できることがポイントです。

HDFSスナップショットの特徴

HDFSスナップショットには以下の特徴があります。

  • ユーザ単位で実行可能

    スナップショットは、特定のユーザのみが取得できるわけでなく、HDFSにアクセスできるユーザであれば誰でも取得できます。

  • ディレクトリ単位での実行

    スナップショットはディレクトリ単位で指定して取得します。

  • Read-Onlyである

    取得したスナップショットはRead-Onlyとして扱われます。スナップショットに対して書き込みはできません。

  • 65536世代までスナップショットを取得可能

    デフォルトで65536世代まで、指定したディレクトリのスナップショットを取得できます。

  • スナップショットのためのリソースの増加はメタ情報のみ

    スナップショットの状態は、NameNodeのメタ情報の操作で実現します。DataNodeで管理されているブロックをコピーするわけではありません。そのため、HDFSの容量には影響を与えません。

HDFSスナップショットの操作

それでは、HDFSスナップショットを扱ってみます。

HDFSスナップショット取得可能設定

スナップショットは、何もしない状態では取得できません。以下のようなメッセージが出力されるだけです。

[sinchii@ip-10-0-0-4 ~]$ hdfs dfs -createSnapshot sample shot1
createSnapshot: Directory is not a snapshottable directory: /user/sinchii/sample

スナップショットを取得したいディレクトリがある場合は、あらかじめHDFSスーパーユーザ(NameNodeを起動しているユーザ)が、対象のディレクトリをスナップショット取得可能ディレクトリに設定しなければなりません。

[hdfs@ip-10-0-0-4 ~]$ hdfs dfsadmin -allowSnapshot /user/sinchii/sample
Allowing snaphot on /user/sinchii/sample succeeded

なお、スナップショット取得不可ディレクトリに変更する場合は、スナップショットが無い状態で、HDFSスーパーユーザによりdisallowSnapshotコマンドを実行します。

[hdfs@ip-10-0-0-4 ~]$ hdfs dfsadmin -disallowSnapshot /user/sinchii/sample
Disallowing snaphot on /user/sinchii/sample succeeded

HDFSスナップショット取得可能ディレクトリ一覧

さまざまなディレクトリをスナップショット取得可能ディレクトリにする場合、どのディレクトリが対象か分からなくなることもあります。その場合は、"hdfs lsSnapshottableDir"コマンドを実行することで確認可能です。

[sinchii@ip-10-0-0-4 ~]$ hdfs lsSnapshottableDir
drwxr-xr-x 0 sinchii hadoop 0 2013-12-21 00:09 0 65536 /user/sinchii/sample
drwxr-xr-x 0 sinchii hadoop 0 2013-12-21 00:29 0 65536 /user/sinchii/sample2

スナップショット取得

まず、スナップショットを取得するディレクトリ(sampleディレクトリ)には、以下のデータが含まれているとします。

[sinchii@ip-10-0-0-4 ~]$ hdfs dfs -ls -R sample
-rw-r--r-- 3 sinchii hadoop 109229073 2013-12-21 00:32 sample/data1.log
drwxr-xr-x - sinchii hadoop 0 2013-12-21 00:36 sample/subdir1
-rw-r--r-- 3 sinchii hadoop 59941262 2013-12-21 00:36 sample/subdir1/data2.log
drwxr-xr-x - sinchii hadoop 0 2013-12-21 00:09 sample/subdir2

このディレクトリに対して、スナップショットを取得します。

# hdfs dfs -createSnapshot <取得ディレクトリのパス> [スナップショット名]
# スナップショット名を指定しない場合、取得した時刻を名前に含める(例: s20131221-054316.743)
[sinchii@ip-10-0-0-4 ~]$ hdfs dfs -createSnapshot sample shot1
Created snapshot /user/sinchii/sample/.snapshot/shot1

取得したスナップショットは、"<ディレクトリ>/.snapshot/[スナップショット名]" で確認できます。"hdfs dfs -ls"コマンドを実行します。

[sinchii@ip-10-0-0-4 ~]$ hdfs dfs -ls -R sample/.snapshot/shot1
-rw-r--r-- 3 sinchii hadoop 109229073 2013-12-21 00:32 sample/.snapshot/shot1/data1.log
drwxr-xr-x - sinchii hadoop 0 2013-12-21 00:36 sample/.snapshot/shot1/subdir1
-rw-r--r-- 3 sinchii hadoop 59941262 2013-12-21 00:36 sample/.snapshot/shot1/subdir1/data2.log
drwxr-xr-x - sinchii hadoop 0 2013-12-21 00:09 sample/.snapshot/shot1/subdir2

なお、".snapshot"はスナップショット専用のディレクトリです。一般の利用者がmkdirコマンドなどで作成することはできません。また、スナップショットの保存先を".snapshot"から変更することもできません。

さらに、スナップショット取得可能なディレクトリ内のサブディレクトリやファイルのみを指定してスナップショットを取得することもできません。

スナップショットの比較

スナップショットの取得ごとに対象ディレクトリのファイルやディレクトリが変化することはあります。その場合、スナップショット間で違いを確認するケースもあります。この場合は、"hdfs snapShotDiff"コマンドで確認可能です。

# hdfs snapshotDiff <スナップショット対象ディレクトリ> <スナップショット名1> <スナップショット名2>
[sinchii@ip-10-0-0-4 ~]$ hdfs snapshotDiff sample shot1 shot3
Difference between snapshot shot1 and snapshot shot3 under directory /user/sinchii/sample:
M .
+ ./messages

このdiffは、HDFS上でのINodeの状態を比較します。そのため、HDFS上のファイルを削除->同じファイルの登録のようなことを行い、ファイル名やファイルの中身が同じであったとしてもdiffコマンドでは異なると判断されます。

[sinchii@ip-10-0-0-4 ~]$ hdfs snapshotDiff sample shot3 shot4
Difference between snapshot shot3 and snapshot shot4 under directory /user/sinchii/sample:
M .
- ./messages
+ ./messages

スナップショット一覧の確認

スナップショットを何度も取得すると、いつ・いくつ取得したか分からなくなることが有ります。その場合は、"hdfs dfs -ls"コマンドで、確認します。

[sinchii@ip-10-0-0-4 ~]$ hdfs dfs -ls sample/.snapshot
Found 3 items
drwxr-xr-x - sinchii hadoop 0 2013-12-21 00:41 sample/.snapshot/shot1
drwxr-xr-x - sinchii hadoop 0 2013-12-21 00:49 sample/.snapshot/shot2
drwxr-xr-x - sinchii hadoop 0 2013-12-21 00:51 sample/.snapshot/shot3
drwxr-xr-x - sinchii hadoop 0 2013-12-21 01:05 sample/.snapshot/shot4

スナップショットの削除

特定のスナップショットを削除したい場合は、"hdfs dfs -deleteSnapshot"コマンドを実行します。例えば、"スナップショット一覧の確認"の状態からshot4を削除する場合は、以下の通りです。

# hdfs dfs -deleteSnapshot <ディレクトリ> <スナップショット名>
[sinchii@ip-10-0-0-4 ~]$ hdfs dfs -deleteSnapshot sample shot4

削除できたかどうかは、"hdfs dfs -ls"コマンドで確認します。

[sinchii@ip-10-0-0-4 ~]$ hdfs dfs -ls sample/.snapshot
Found 3 items
drwxr-xr-x - sinchii hadoop 0 2013-12-21 00:41 sample/.snapshot/shot1
drwxr-xr-x - sinchii hadoop 0 2013-12-21 00:49 sample/.snapshot/shot2
drwxr-xr-x - sinchii hadoop 0 2013-12-21 00:51 sample/.snapshot/shot3

コマンド出力結果の通り削除されていることが分かります。なお、スナップショットの削除は一つずつしか実行できません。

スナップショットからのデータの取り出し

取得したスナップショットのデータを取得したい場合は、"hdfs dfs -get"コマンドや"hdfs dfs -cp"コマンドで取得できます。例えば、以下のようにコマンドを実行します。

[sinchii@ip-10-0-0-4 ~]$ hdfs dfs -ls sample/.snapshot/shot3
Found 4 items
-rw-r--r-- 3 sinchii hadoop 109229073 2013-12-21 00:32 sample/.snapshot/shot3/data1.log
-rw-r--r-- 3 sinchii hadoop 1366 2013-12-21 00:50 sample/.snapshot/shot3/messages
drwxr-xr-x - sinchii hadoop 0 2013-12-21 00:36 sample/.snapshot/shot3/subdir1
drwxr-xr-x - sinchii hadoop 0 2013-12-21 00:09 sample/.snapshot/shot3/subdir2
[sinchii@ip-10-0-0-4 ~]$ hdfs dfs -get sample/.snapshot/shot3/messages .
[sinchii@ip-10-0-0-4 ~]$ ls -al
total 4
-rw-r--r--. 1 sinchii sinchii 1366 Dec 21 01:44 messages

スナップショットの操作に関しては以上のコマンドで実現できます。スナップショットのためのコマンドとこれまで存在したコマンドを組み合わせることで、容易に操作ができます。

HDFSスナップショットの利用シーン

HDFSスナップショットの利用シーンとしては、特に以下の場合に有効だと思います。

  • HDFS上のオペレーションミス

    HDFS上に保存している、重要なデータをオペミスによって削除することはあるとおもいます。HDFS外に同じデータがある場合でも、そのデータを再度HDFSに格納するとなると、それなりに時間を要することになります。HDFSのスナップショットを取得することで、重要なデータを消した場合でも容易に復旧させることができます。

  • HDFS上のデータのバックアップ

    データが度々変わるようなディレクトリに対してスナップショットを取得することで、任意のタイミングでのHDFSの状態を抑えておきバックアップに利用することも可能です。

その他

  • スナップショットを取得すると、対象のファイルのレプリカ数も維持される。スナップショット取得後にsetrepコマンドでレプリカ数を減らしても実際には減らない。

  • HDFS上のファイルはINodeFile、 INodeDirectoryオブジェクトで扱われるが、スナップショット対象のファイルやディレクトリは、INodeFileWithSnapshot、INodeDirectoryWithSnapshotに置き換わる。replaceXXX(XXXは任意)というメソッドで置き換えている。

おわりに

HDFSスナップショットは、作成・削除・比較といった一通りの操作は実現できるようになったといえます。今後は、distcpやHive、HBaseとの連携する仕組みの開発、一時的なファイルの除外などが機能追加される予定です。
オペミスからのリカバーやバックアップという点で利用しましょう。

明日は、@yamakatuさんです。