Hadoop とは大量のデータを複数のマシンに分散して処理できるオープンソースのプラットフォームです。
ここではHadoopを運用していく上で必要な知識をメモ程度を残していきます。
パラメータ関連
- ''hadoop-env.sh''
''パラメータ'' ''説明'' ''補足'' HADOOP_OPTS デーモンのJava起動オプション ヒープサイズを設定したり、並列GC、コンカレントGCを使用するなど -server -XX:+UseParallelGC -XX:+UseConcMarkSweepGC -Xms1500m -Xmx1500m
- ''hadoop-site.xml''
mapred.child.java.opts の設定は、JobConf実行時に設定可。
''パラメータ'' ''説明'' ''補足'' mapred.tasktracker (map,reduce).tasks.maximum 個々のTaskTrackerで同時に走るMap/Reduceの最大タスク数 デフォルトは2、コア数-1くらいが良い感じ mapred.child.java.opts MapReduceの子JVMのオプション メモリが足りない時に、最大ヒープサイズを設定するなど
(hadoop-site.xml の設定項目は実行時に設定できるものとできないものがある)
SequenceFile
SequenceFile は、<key, value>形式でデータを保持する。テキストをそのままMapで読み込むと、keyにバイトオフセット、valueに入力テキストが入るが、SequenceFile形式だとkey, valueをそのままMapの入力とすることができる。また、圧縮していても各ノードに分散される(gzipは分散されない)。hadoop fs -text とすれば、コマンドラインからテキスト形式で内容を出力できる。
- Jobのinputとoutputを SequenceFile 形式にする
- テキスト形式で内容を確認
$ hadoop fs -text SequenceFile.out
HadoopではgzipファイルをMapに直接入力することができ、自動で展開してくれる。ただし、分割して各ノードに分散してくれない。1つのgzipファイルは1つのノードで処理される。
圧縮
- 可能な限りスプリット可能な圧縮形式で圧縮
- 空間,時間効率のバランスを考えるとLZO推奨
- サイズの大きなgzipファイルを入力にしてはいけない
- gzipファイルを利用する場合には、1ブロックサイズにマッチしていると効果的
- 出力データも圧縮
ブロックサイズ最適化
Hadoop は大きなファイルをシーケンシャルに読み書きするのに適した設計がされているので、小さいファイルを大量に扱うのは苦手。空間効率が悪い上に NameSpace を大量に消費して NameNode に負荷をかける。さらに MapReduce では、デフォルトで1つのファイルにつき少なくとも1つの MapTask が立ち上がってしまい非効率。
- 保存領域を節約するためHadoopアーカイブを利用
- CombineFileInputFormat を利用
(小さなファイルをまとめて一つの InputSplit にすることで MapTask 数を削減できる) - mapred.min.split.size をブロックサイズ以上に設定
(ブロックサイズ以上にスプリットされるので MapTask 数を削減できる)
Map出力データ
- Map出力データは圧縮すること
Map出力ファイルはローカルに書き出されるので、データ量の削減はディスクI/Oの削減に効果がある。また、シャッフル処理されるときネットワークを通過する場合が多いので、データ転送量の削減にも効果的。ディスクI/Oと比べてCPUに余裕があれば圧縮処理はボトルネックになりにくい。
ジョブ一般
- 小さなデータでもクラスタ外のデータを都度参照してはいけない
処理に必要な小さなデータについては、DistributedCache を利用する。 - Mapタスク数がデータ量に見合っているか注意すること
- Reduceタスク数が多すぎないか注意すること
TaskTracker毎にReduceタスク数ぶんだけMap出力パーティションが作成されるので、シャッフルフェイズがボトルネックとなる可能性がある。
Hive
- 同じテーブルに対して複数回クエリを発行する場合には、ストレージ形式にSequenceFileを圧縮設定で用いる。
- クエリを複数実行し、かつ中間データが必要ない場合には、Pigで記述出来ないか検討する。