HadoopのサンプルのTeraSortのメモ。
|
TeraSortは、大量データのソートを行うサンプル。
どうもHadoop以外のソートとベンチマーク(ソート速度)を競う為のものっぽい。
(データの改行コードはCRLFだし、レプリケーション数1でファイルを作るようになっている)
TeraSortを使うには、TeraGenで入力データを作る。
ここではCDH3のhadoop-examplesを擬似分散モードで実行している。
まず、TeraGenでソートの入力データを作る。
$ hadoop jar /usr/lib/hadoop/hadoop-examples.jar teragen 100 input
第1引数はデータの行数を指定する。1行は100バイト出力されるので、この例だと1万バイトのデータが作られる。(改行コードはCRLFの2バイトなので、データ文字列は1行当たり98バイト)
第2引数は出力先のディレクトリー名。
なお、MapReduceが動いてファイルが作られる。(バイト数に応じてファイルが複数出来る)
$ hadoop fs -ls input
Found 4 items
-rw-r--r-- 1 hishidama supergroup 0 2012-04-03 19:58 /user/hishidama/input/_SUCCESS
drwxr-xr-x - hishidama supergroup 0 2012-04-03 19:58 /user/hishidama/input/_logs
-rw-r--r-- 1 hishidama supergroup 5000 2012-04-03 19:58 /user/hishidama/input/part-00000
-rw-r--r-- 1 hishidama supergroup 5000 2012-04-03 19:58 /user/hishidama/input/part-00001
そして、TeraSortでソートを実行する。
$ hadoop jar /usr/lib/hadoop/hadoop-examples.jar terasort input output
$ hadoop fs -ls output
Found 3 items
-rw-r--r-- 1 hishidama supergroup 0 2012-04-03 19:59 /user/hishidama/output/_SUCCESS
drwxr-xr-x - hishidama supergroup 0 2012-04-03 19:59 /user/hishidama/output/_logs
-rw-r--r-- 1 hishidama supergroup 10000 2012-04-03 19:59 /user/hishidama/output/part-00000
結果ファイルは1つにまとまるようだ。
ちなみに、TeraSort実行後にinputを見てみると、変なファイルが出来てる。
$ hadoop fs -ls input
Found 5 items
-rw-r--r-- 1 hishidama supergroup 0 2012-04-03 19:58 /user/hishidama/input/_SUCCESS
drwxr-xr-x - hishidama supergroup 0 2012-04-03 19:58 /user/hishidama/input/_logs
-rw-r--r-- 1 hishidama supergroup 129 2012-04-03 19:59 /user/hishidama/input/_partition.lst
-rw-r--r-- 1 hishidama supergroup 5000 2012-04-03 19:58 /user/hishidama/input/part-00000
-rw-r--r-- 1 hishidama supergroup 5000 2012-04-03 19:58 /user/hishidama/input/part-00001
ところで、スタンドアローンモードでTeraSortを実行したら、例外が発生した。
$ hadoop jar /usr/lib/hadoop/hadoop-examples.jar teragen 100 input $ hadoop jar /usr/lib/hadoop/hadoop-examples.jar terasort input output 〜 java.lang.RuntimeException: Error in configuring object at org.apache.hadoop.util.ReflectionUtils.setJobConf(ReflectionUtils.java:93) at org.apache.hadoop.util.ReflectionUtils.setConf(ReflectionUtils.java:64) at org.apache.hadoop.util.ReflectionUtils.newInstance(ReflectionUtils.java:117) at org.apache.hadoop.mapred.MapTask$OldOutputCollector.(MapTask.java:481) at org.apache.hadoop.mapred.MapTask.runOldMapper(MapTask.java:391) at org.apache.hadoop.mapred.MapTask.run(MapTask.java:325) at org.apache.hadoop.mapred.LocalJobRunner$Job.run(LocalJobRunner.java:210) Caused by: java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:616) at org.apache.hadoop.util.ReflectionUtils.setJobConf(ReflectionUtils.java:88) ... 6 more Caused by: java.lang.IllegalArgumentException: can't read paritions file at org.apache.hadoop.examples.terasort.TeraSort$TotalOrderPartitioner.configure(TeraSort.java:213) ... 11 more Caused by: java.io.FileNotFoundException: File _partition.lst does not exist. at org.apache.hadoop.fs.RawLocalFileSystem.getFileStatus(RawLocalFileSystem.java:408) at org.apache.hadoop.fs.FilterFileSystem.getFileStatus(FilterFileSystem.java:251) at org.apache.hadoop.fs.FileSystem.getLength(FileSystem.java:825) at org.apache.hadoop.io.SequenceFile$Reader. (SequenceFile.java:1480) at org.apache.hadoop.io.SequenceFile$Reader. (SequenceFile.java:1475) at org.apache.hadoop.examples.terasort.TeraSort$TotalOrderPartitioner.readPartitions(TeraSort.java:153) at org.apache.hadoop.examples.terasort.TeraSort$TotalOrderPartitioner.configure(TeraSort.java:210) ... 11 more
「_partition.lst」というファイルが見つからなくて落ちている。
どうもTeraSortでは、ジョブの実行に先立って_partition.lstというファイルに情報を書き出し、Hadoopの分散キャッシュの仕組みを使って各ノードへ配布し、MapTaskで読み込んでいるようだ。
試しに擬似分散環境のHDFS上に出来ていた_partiton.lstをローカルに持ってきて実行したら、ちゃんと動いた(苦笑)
$ hadoop fs -get hdfs://localhost/user/hishidama/input/_partition.lst .
$ hadoop jar /usr/lib/hadoop/hadoop-examples.jar terasort input output
_partition.lstを作って読み込んでいる箇所は、以下のようになっている。
ソース | 擬似分散モードでの値 | 単独モードでの値 | ||
---|---|---|---|---|
書き出し | TeraSort#run() |
Path partitionFile = new Path(inputDir, TeraInputFormat.PARTITION_FILENAME); |
hdfs://ホスト/user/hishidama/ |
file:/カレントディレクトリー/ |
DistributedCache.addCacheFile(partitionUri, job); |
||||
読み込み | TeraSort$TotalOrderPartitioner# configure() |
FileSystem fs = FileSystem.getLocal(job); |
_partition.lst |
_partition.lst |
FileSystem#getFileStatus() |
(実体はRawLocalFileSystem) | |||
RawLocalFileSystem#pathToFile() |
path = new Path(getWorkingDirectory(), path); |
file:/var/lib/hadoop〜/cache/mapred/〜/_parition.lst |
file:/カレントディレクトリー/_partition.lst |
キャッシュファイルの読み込みは(キャッシュはローカルにコピーされるので)RawLocalFileSystemを使うのだが、これのワークディレクトリー(getWorkingDirectory()
)は、System.getProperty("user.dir")
の指す場所になっている。
分散モードで動かしている場合、タスクに対してはタスク専用のJavaVMが起動されるが、その際のuser.dirは「file:/var/lib/hadoop-0.20/cache/mapred/〜
」を指している。要するに、キャッシュの場所を指しているので、ちゃんとキャッシュファイルが取得できる。
しかしスタンドアローン(単独)モードの場合は書き出しと読み込みのJavaVMは同一なので、ワークディレクトリーはカレントディレクトリーのままであり、キャッシュファイルの正しい場所を指さない。そのせいで_partition.lstが見つからないという事になっている。
スタンドアローンモードでは分散キャッシュが機能しないのかなぁ…と思ったが、確かAsakusaFWは分散キャッシュを使っているが(JUnitによるテスト時に)スタンドアローンモードで動いているので、大丈夫なはず。
という事は、TeraSortの分散キャッシュのコーディングがおかしいのだろうか。