昨日に引き続き Hadoop と Ruby について書いていきます。
Hadoop Streaming を使う
すでに説明した通り Hadoop Streaming を利用すると Ruby などのスクリプト言語で Hadoop を利用できます。
GitHub の以下の場所にサンプルとなるデータとソースコードを用意しました。
https://github.com/ynakayama/sandbox/tree/master/ruby/hadoop/streaming/example
これを元に、実際にどのように Hadoop Streaming のためのプログラミングをしていくかを説明していきましょう。
標準入出力を利用したテスト
上記のファイルの構成は以下のようになっています。
ファイル | 説明 |
---|---|
test.json | 検査対象のデータが格納されているファイル |
lib/mapper.rb | Mapper のソースコード |
lib/reducer.rb | Reducer のソースコード |
標準入出力を利用して次のようにパイプで処理を渡せば Hadoop で実行したときと同じ出力を得られます。
cat test.json | ruby lib/mapper.rb | sort | ruby lib/reducer.rb
ソースコードの内容は前回説明したものと同一です。
以下の出力が得られます。実際にはソースコードをもう少し工夫して先頭のキーが無い行を削除したほうが良いでしょう。
0
012345ABCDEF 1
012345ABCDFF 2
012346ABCDEF 4
01236AABCDEF 3
結果が本当に正しいか grep と wc で検査してみます。
$ grep 012345ABCDEF test.json | wc -l
1
$ grep 012345ABCDFF test.json | wc -l
2
$ grep 01236AABCDEF test.json | wc -l
3
$ grep 012346ABCDEF test.json | wc -l
4
どうやら正しくカウントされているようですね。 Hadoop で実行することで、これらの処理が一部分散して実行されるというメリットを得られるわけです。
Hadoop Streaming では次のように実行します。
/usr/bin/hadoop \
jar hadoop-streaming.jar \
-D mapred.reduce.tasks=1 \
-file lib/mapper.rb \
-mapper mapper.rb \
-file lib/reducer.rb \
-reducer reducer.rb \
-input s3n://bucket_name/XXX/test.json \
-output out
非常に長いコマンドになってしまいました。
上記の例では /usr/bin/hadoop を利用して hadoop-streaming.jar を利用し Amazon S3 上の test.json を読み込み結果を HDFS 上の out というディレクトリに出力しています。
毎回このようなコマンドを入力するのは非常に煩雑です。そこで後述するフレームワークを利用します。
Hadoop Streaming with Ruby
煩雑さを軽減するために作成したフレームワークが以下のものです。
Hadoop Streaming
https://github.com/ynakayama/hadoop-streaming
フレームワークと言ってもシェルスクリプトを薄くラップしただけのものに過ぎません。基本的な環境設定を config/env.conf ファイルでおこなえるようになっています。これは実際にはシェルスクリプトで使われる環境変数を定義するようになっています。
リポジトリの data/shakespeare/ の下にシェイクスピアの作品が用意されていますので確認してみてください。サンプルとして Mapper と Reducer にはこれらの平均単語長を調べるコードが書かれています。
単純に標準入出力のみを利用して実行するには script/simple とタイプします。すると log/result.log に計算結果が出力されます。
実際に Hadoop を利用するには Hadoop がインストールされたクライアントノードで bin/run & してください。
詳細はドキュメントを参照してください。
このフレームワークは実際には環境設定した内容をもとに上記のコマンドを発行しているシェルスクリプトにすぎません。これを使うメリットは次の通りです。
- 面倒なコマンドを自前で発行しなくて良い
前述の通り Hadoop Streaming を利用するには長いコマンドを入力する必要がありますが、これらを環境設定ファイルなどから組み立ててくれるので利用者はそれを意識する必要がありません。
- ジョブの開始時刻、終了時刻、正常終了などがログに出力される
ジョブログ (デフォルトでは log/job.log) にはジョブの開始終了時間、正常終了か否かが出力されます。正常終了の判断は HDFS の出力ディレクトリに _SUCCESS ファイルが生成されたか否かでおこなっています。
- 結果がログに出力される
Hadoop Streaming では既定で HDFS に結果が出力されますがこれが log/result.log に落ちてきます。
複数の Reducer には今のところ対応していません。簡易なフレームワークなので適宜 pull request していただけばマージ致します。
まとめ
Hadoop Streaming + Ruby でどのようにプログラミングをしていったらいいか、またそれらを簡単にするフレームワークについて紹介しました。