たごもりすメモ

コードとかその他の話とか。

HDFSのファイルオペレーション各種 #hadoopAC11jp

この記事は hadoopアドベントカレンダー の14日目の記事です。

みなさんHDFS使ってますか。使ってますよね。最近はgluster fsなどの選択肢も出てきていますが、まだ第一の選択肢はHDFSという人がほとんどだと思います。
で、HDFSのファイル操作をどうしようか悩みますよね。めんどくさいです。いくつかあるので比較してみましょう。

hadoop fsコマンド

みんな大好きhadoop fs。日に100回くらいは叩きますね。基本的にはみんなこれを使うでしょうか。ただし以下いくつかの「たるいなー」という点があります。

Hadoopがインストール・設定されていないと動かない

あたりまえなんですけど意外にめんどくさいですね。
Hadoopの処理対象となるファイルはもちろんHadoopクラスタ「以外」のサーバから出てくるわけで、そこからも直接ファイルをHDFSに突っ込みたいなーというのは割と自然な欲求のような気がします。自分の扱ってる環境だと基本的にサーバにJVMも入ってないんで、各サーバにHadoopの環境を用意するのはだいぶハードルが高いです。

JVMの起動時間を待つ必要がある

普通のファイルシステム上での操作と同じ感覚でコマンドを叩いていると、これが意外にストレスですね。
hadoop fsコマンドはJava実装のHDFSClientをつかってあらゆる操作を行うため、何をやるにしてもJVMの起動を待つ必要があります。普通のファイルシステムであれば mv などは一瞬で操作が終わるもので、もちろんそれはHDFS上でもほぼ同じ(renameのコストはかなり低い)ですが、実際にはJVMの起動・停止の待ちがあってかなり待ちます。

FUSE hdfs

Linux(やその他のOS)には FUSE(filesystem in userspace) という機構があり、それを介してHDFSに接続することでLinux上でHDFSをmountする(したように見せる)ことができます。Hadoop Wikiにも解説(英語)があります。また自分も以前にblogエントリを書きました。
fuseでhdfsをmount - tagomorisのメモ置き場

利点はLinux上での通常のファイル操作がそのまま行えること。じつに大きい利点だと思います。だいぶいいですね。
しかしこれはこれで、どうにも信用のならない点がいくつかあります。

libhdfsのバージョン問題

FUSE hdfsHadoopのパッケージに添付の libhdfs を使用します。簡単に解説するとlibhdfsとはHDFS関連のオペレーションを行うためのC実装のライブラリなのですが、その実態は JNI でJava実装のコード(HDFSClient)を呼び出しているだけです。
このため、Hadoopのバージョンに強く依存します。Hadoop自体のバージョンを上げた場合にはクライアント側でも追随しなくてはなりません。またクライアント側のバージョンアップ時にはHDFSのumount、libhdfs の更新、fuse_dfs の再コンパイルとインストール、そしてHDFSのmountという手順を踏むことになります。だいぶ面倒な上にmountの切断時間が長くて悲しいですね。これを関連するクライアント全台で行うと考えるのはだいぶげんなりします。

パフォーマンスの問題

FUSE hdfsはバックエンドとしてひとつのプロセスがHadoopクラスタと通信を行います。mountしてあるHDFS領域に関するすべてのオペレーションをこのプロセスが担当するので、通信量などによってはパフォーマンスが出ないことが予想されます。せっかくファイルシステム側が分散システムなのに、手元の1プロセスに制約されるのは、仕方がないとはいえ残念ですね。
特に最近のCPUは多コア化して各コアの処理能力はそこまで求めない場合が多く、このような環境だと1プロセスに処理が集中するモデルは不利となります。またバースト的に負荷がかかったときに、FUSE hdfs自体の安定性があまり良くない気もしています。*1

Hoop

という現状に問題意識があったのか、最近 Hoop というツールが出てきました。Clouderaから公開されたものですが、Hadoop本体へのマージが進められたようで、0.23.1(および0.24)のツリーにおいてマージされたようです。

[HDFS-2178] HttpFS - a read/write Hadoop file system proxy - ASF JIRA

HoopはWeb(REST) API経由でHDFS上のファイルオペレーションを行うもので、Hoop Serverをどこかに立てて使います。クライアントはHTTPリクエストを送れさえすれば何でもいいということで、これまでのHadoopに密結合された環境を要求しないのが最大の利点と言えると思います。
なお、現状(?)の0.20系においても、Clouderaからリリースされているバージョンを使えば既に使用できます。これについてもエントリを過去に書きました。

Hoop (HDFS over HTTP) を試してみた - tagomorisのメモ置き場
Hoopの性能を確認してみたらもうlibhdfsとかオワコンでHoop使えって結果になった - tagomorisのメモ置き場

とはいえHoopに問題が無いかといえば、無いわけでもないです。

Hoop ServerがSPOF

前述した通り全クライアントがHoop Server経由で通信を行うため、これが障害に遭うと全クライアントが通信できなくなります。ちょっと問題です。
ただ、複数立てられるので、怖い人は複数立てておけばよいでしょう。だいたい現状だとHDFSのNameNodeがSPOFな時点で……って感じですね!

またHoop Serverのパフォーマンスを気にされる人がいるかもしれませんが、これについては前述のエントリでとったベンチマーク結果の通り、基本的に問題なさそうという認識でいます。

HTTPでリクエストを投げる必要がある

これが一番の障壁に思う人が多いかも。
普通のファイルシステム操作とだいぶ異なるオペレーションを行わないといけなくなるため、扱う側にとってあれこれ考えを変える必要があります。REST APIのリファレンスを見ればわかる通り curl コマンドを叩けばどの操作もできるんですが、ちょっと敷居が高いのは確かですね。
普段のオペレーションに使いたい場合はREST APIを叩く専用のラッパーコマンドなりを自作するのが良いでしょう。

まとめ

HDFS上のファイルのオペレーションを行う方法をみっつ挙げましたが、どれも一長一短な側面はあります。個人的にはHoopはいいなと思いますが、みなさんの環境や運用状況にあわせて適切に選ぶとよいのではないでしょうか!

*1:あまり明確な証拠が出せるものがないのですが!