LoginSignup
3
3

More than 5 years have passed since last update.

Running own MapReduce on MacOSX

Posted at

MaxOSXで自分で書いたMapReduceプログラムを走らせる。

OS HomeBrew JDK Hadoop
MacOSX 10.9.4 0.9.5 1.8.0 2.4.1

Hadoopのインストール

HadoopはHomebrewで入れたものを使う。

$ brew install hadoop

インストール先は下記

$ cd /usr/local/Celler/hadoop/2.4.1
$ bin/hadoop version
Hadoop 2.4.1
Subversion http://svn.apache.org/repos/asf/hadoop/common -r 1604318
Compiled by jenkins on 2014-06-21T05:43Z
Compiled with protoc 2.5.0
From source with checksum bb7ac0a3c73dc131f4844b873c74b630
This command was run using /usr/local/Cellar/hadoop/2.4.1/libexec/share/hadoop/common/hadoop-common-2.4.1.jar

インストールは完了。Stand Aloneか擬似分散モードの設定はここを参照。

自作MapReduceの作成

Hadoop Tutorialにある通りのWordCountを実装。
MapReduce2はApache Commonsも必要なようだったので今回はMapReduce1で実装。

import java.io.IOException;
import java.util.StringTokenizer;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

public class WordCount {

  public static class TokenizerMapper
       extends Mapper<Object, Text, Text, IntWritable>{

    private final static IntWritable one = new IntWritable(1);
    private Text word = new Text();

    public void map(Object key, Text value, Context context
                    ) throws IOException, InterruptedException {
      StringTokenizer itr = new StringTokenizer(value.toString());
      while (itr.hasMoreTokens()) {
        word.set(itr.nextToken());
        context.write(word, one);
      }
    }
  }

  public static class IntSumReducer
       extends Reducer<Text,IntWritable,Text,IntWritable> {
    private IntWritable result = new IntWritable();

    public void reduce(Text key, Iterable<IntWritable> values,
                       Context context
                       ) throws IOException, InterruptedException {
      int sum = 0;
      for (IntWritable val : values) {
        sum += val.get();
      }
      result.set(sum);
      context.write(key, result);
    }
  }

  public static void main(String[] args) throws Exception {
    Configuration conf = new Configuration();
    Job job = Job.getInstance(conf, "word count");
    job.setJarByClass(WordCount.class);
    job.setMapperClass(TokenizerMapper.class);
    job.setCombinerClass(IntSumReducer.class);
    job.setReducerClass(IntSumReducer.class);
    job.setOutputKeyClass(Text.class);
    job.setOutputValueClass(IntWritable.class);
    FileInputFormat.addInputPath(job, new Path(args[0]));
    FileOutputFormat.setOutputPath(job, new Path(args[1]));
    System.exit(job.waitForCompletion(true) ? 0 : 1);
  }
}

コンパイル

上記で作成したファイルを下記に置く。

$ mkdir -p workspace/wordcount
$ mv WordCount.java workspace/wordcount/

コンパイルを行う

$ javac -classpath libexec/share/hadoop/common/hadoop-common-2.4.1.jar:libexec/share/hadoop/mapreduce/hadoop-mapreduce-client-core-2.4.1.jar -d workspace/wordcount workspace/wordcount/WordCount.java

Hadoop1.xではhadoop-coreというjarがあるらしいけれど2.xだと見つからなかった。どうやらhadoop-commonとhadoop-mapreduce-client-coreをclasspathに含めればコンパイルできるらしい。でもいちいち何が必要判断するのはめんどくさいのでhadoopのclasspathを与えてやる。

$ javac -classpath `bin/hadoop classpath` -d workspace/wordcount workspace/wordcount/WordCount.java

jarに固める。

$ jar -cvf workspace/wordcount/wordcount.jar -C workspace/wordcount/ .

これで必要な実行ファイルができた。これを実行してみる。

MapReduceの実行

今回は擬似分散モードでYARN上で稼働させる。

conf

core-site.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
  <property>
    <name>fs.defaultFS</name>
    <value>hdfs://localhost:9000</value>
  </property>
</configuration>
hdfs-site.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
   <property>
     <name>dfs.replication</name>
     <value>1</value>
   </property>
</configuration>
mapred-site.xml
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
  <property>
    <name>mapreduce.framework.name</name>
    <value>yarn</value>
  </property>
</configuration>
yarn-site.xml
<?xml version="1.0"?>
<property>
  <name>yarn.nodemanager.aux-services</name>
  <value>mapreduce_shuffle</value>
</property>
</configuration>

HDFSの起動

$ sbin/start-dfs.sh

YARNの起動

$ sbin/start-yarn.sh

確認

各コンポーネントが起動していることを確認する。

$ jps
4432 DataNode
4342 NameNode
4539 SecondaryNameNode
4747 NodeManager
4654 ResourceManager
4878 Jps

入力データの作成

$ cat input/word1                                                                                                                                              
a b c d a a b a a a
$ cat input/word2
a a b c c c

これらを集計するためHDFSにコピーする。

$ bin/hadoop fs -mkdir /hadoop/input
$ bin/hadoop fs -copyFromLocal input/word1 /hadoop/input/word1
$ bin/hadoop fs -copyFromLocal input/word2 /hadoop/input/word2

実行

# 作成したjarファイルから実行対象のクラス名WordCountを指定する
$ bin/hadoop jar workspace/wordcount/wordcount.jar WordCount /hadoop/input /hadoop/output

outputディレクトリに集計結果がでているはず。

kaisasak% bin/hadoop fs -cat /hadoop/output/part-r-00000
a       8
b       3
c       4
d       1
3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3