ITPub博客

首页 > 大数据 > Hadoop > 开发一个mapreduce程序

开发一个mapreduce程序

原创 Hadoop 作者:paololiu 时间:2015-08-03 11:34:46 0 删除 编辑

整个项目以hadoop自带的hadoop-mapreduce-examples-2.6.0.jar为例。

2.1新建一个项目

说明:这里没有使用hadoop-eclipse-plugin插件,而是直接新建一个java project,和hadoop-mapreduce-examples-2.6.0.jar一样,完成后打包成jar文件在hadoop集群中运行。

打开eclipse,file---new---java project



2.2新建一个lib文件夹,并将hadoop三个jar复制进去



三个
jar包所在hadoop的路径:

hadoop/share/hadoop/yarn/lib/commons-cli-1.2.jar

hadoop/share/hadoop/common/hadoop-common-2.6.0.jar

hadoop/share/hadoop/mapreduce/hadoop-mapreduce-client-core-2.6.0.jar


2.3将三个jar包add to build path



2.2jar包入口class

最终我们会将项目打包成一个jar文件放到hadoop集群中去运行。但是在打包jar文件的时候只能指定一个main class,那么每一个需求就要打包成一个jar文件,在使用管理上都很麻烦。通过模仿hadoop自带的样例hadoop-mapreduce-examples-2.6.0.jar,我们可以为jar包创建一个统一的man class,再通过它去调用其他的man class。

点击(此处)折叠或打开

  1. package exhadp;

  2. import org.apache.hadoop.util.ProgramDriver;

  3. public class hadpdriver {

  4.     public static void main(String[] args) {
  5.         // TODO Auto-generated method stub

  6.         int exitCode=-1;
  7.         ProgramDriver pdg=new ProgramDriver();
  8.         
  9.         try{
  10.             pdg.addClass("getcount", getcount.class, "getcount");
  11.             pdg.addClass("getmax", getmax.class, "getmax");
  12.             pdg.addClass("getsum", getsum.class, "getsum");
  13.             exitCode=pdg.run(args);
  14.         }catch (Throwable e){
  15.             e.printStackTrace();
  16.         }
  17.         
  18.         System.exit(exitCode);
  19.     }
  20. }


调用的方式如下:

[grid@dehadp01 ~]$ hadoop jar exhadp.jar getsum TEST_OBJECTS/part-m-00000 getsum_out


2.3案例文件说明

1,SYS,ICOL$,null,20,2,TABLE,2011-09-17 09:46:13.0,2011-09-17 09:58:00.0,2011-09-17:09:46:13,VALID,N,N,N,1,null

2,SYS,I_USER1,null,46,46,INDEX,2011-09-17 09:46:13.0,2011-09-17 09:46:13.0,2011-09-17:09:46:13,VALID,N,N,N,4,null

3,SYS,CON$,null,28,28,TABLE,2011-09-17 09:46:13.0,2011-09-17 10:04:20.0,2011-09-17:09:46:13,VALID,N,N,N,1,null

4,SYS,UNDO$,null,15,15,TABLE,2011-09-17 09:46:13.0,2011-09-17 09:46:13.0,2011-09-17:09:46:13,VALID,N,N,N,1,null

5,SYS,C_COBJ#,null,29,29,CLUSTER,2011-09-17 09:46:13.0,2011-09-17 09:46:13.0,2011-09-17:09:46:13,VALID,N,N,N,5,null


数据源于oracle数据库内的:select rownum id,a.* from dba_objects a

每一行即是一条记录,中间以“,”分隔,第一列表示id,第二列表示owner,第七列表示object_type,倒数第二列表示status。


2.4求每个owner的最大的id,即select owner,max(id) from t group by owner

点击(此处)折叠或打开

  1. package exhadp;

  2. //完全模仿wordcount的样式

  3. import java.io.IOException;

  4. import org.apache.hadoop.conf.Configuration;
  5. import org.apache.hadoop.fs.Path;
  6. import org.apache.hadoop.io.IntWritable;
  7. import org.apache.hadoop.io.Text;
  8. import org.apache.hadoop.mapreduce.Job;
  9. import org.apache.hadoop.mapreduce.Mapper;
  10. import org.apache.hadoop.mapreduce.Reducer;
  11. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
  12. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
  13. import org.apache.hadoop.util.GenericOptionsParser;

  14. public class getmax {

  15.     // map的过程
  16.     public static class TokenizerMapper extends
  17.             Mapper<Object, Text, Text, IntWritable> {
  18.         public void map(Object key, Text value,
  19.                 Mapper<Object, Text, Text, IntWritable>.Context context)
  20.                 throws IOException, InterruptedException {
  21.             // 将源文件中一行的记录以字符串的形式存入line中
  22.             String line = value.toString();
  23.             String[] strarray = line.split(",");
  24.             // 以“,”为分隔符,第一列(strarray[0])为id,第二列(strarray[1])为owner
  25.             Text owner = new Text(strarray[1]);
  26.             int id = Integer.parseInt(strarray[0]);
  27.             // 将owner做为map的key,id作为value
  28.             context.write(owner, new IntWritable(id));
  29.         }
  30.     }

  31.     // reduce过程
  32.     public static class IntMaxReducer extends
  33.             Reducer<Text, IntWritable, Text, IntWritable> {
  34.         public void reduce(Text key, Iterable<IntWritable> values,
  35.                 Reducer<Text, IntWritable, Text, IntWritable>.Context context)
  36.                 throws IOException, InterruptedException {
  37.             int max = Integer.MIN_VALUE;
  38.             for (IntWritable value : values) {
  39.                 max = Math.max(max, value.get());
  40.             }
  41.             context.write(key, new IntWritable(max));
  42.         }
  43.     }

  44.     // 主程序分别调用map和reduce的过程
  45.     public static void main(String[] args) throws Exception {
  46.         Configuration conf = new Configuration();
  47.         String[] otherArgs = new GenericOptionsParser(conf, args)
  48.                 .getRemainingArgs();
  49.         if (otherArgs.length < 2) {
  50.             System.err.println("Usage: getmax <in> [<in>...] <out>");
  51.             System.exit(2);
  52.         }
  53.         Job job = new Job(conf, "getmax");
  54.         job.setJarByClass(getmax.class);
  55.         job.setMapperClass(TokenizerMapper.class);
  56.         job.setCombinerClass(IntMaxReducer.class);
  57.         job.setReducerClass(IntMaxReducer.class);
  58.         job.setOutputKeyClass(Text.class);
  59.         job.setOutputValueClass(IntWritable.class);
  60.         for (int i = 0; i < otherArgs.length - 1; i++) {
  61.             FileInputFormat.addInputPath(job, new Path(otherArgs[i]));
  62.         }
  63.         FileOutputFormat.setOutputPath(job, new Path(
  64.                 otherArgs[(otherArgs.length - 1)]));

  65.         System.exit(job.waitForCompletion(true) ? 0 : 1);
  66.     }
  67. }


2.5统计每种status的数量,即select status,count(*) from t group by status

点击(此处)折叠或打开

  1. package exhadp;

  2. import java.io.IOException;

  3. import org.apache.hadoop.conf.Configuration;
  4. import org.apache.hadoop.fs.Path;
  5. import org.apache.hadoop.io.IntWritable;
  6. import org.apache.hadoop.io.Text;
  7. import org.apache.hadoop.mapreduce.Job;
  8. import org.apache.hadoop.mapreduce.Mapper;
  9. import org.apache.hadoop.mapreduce.Reducer;
  10. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
  11. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
  12. import org.apache.hadoop.util.GenericOptionsParser;

  13. public class getcount {

  14.     public static void main(String[] args) throws Exception {
  15.         Configuration conf = new Configuration();
  16.         String[] otherArgs = new GenericOptionsParser(conf, args)
  17.                 .getRemainingArgs();
  18.         if (otherArgs.length < 2) {
  19.             System.err.println("Usage: getcount <in> [<in>...] <out>");
  20.             System.exit(2);
  21.         }
  22.         Job job = new Job(conf, "getcount");
  23.         job.setJarByClass(getcount.class);
  24.         job.setMapperClass(TokenizerMapper.class);
  25.         job.setCombinerClass(IntCountReducer.class);
  26.         job.setReducerClass(IntCountReducer.class);
  27.         job.setOutputKeyClass(Text.class);
  28.         job.setOutputValueClass(IntWritable.class);
  29.         for (int i = 0; i < otherArgs.length - 1; i++) {
  30.             FileInputFormat.addInputPath(job, new Path(otherArgs[i]));
  31.         }
  32.         FileOutputFormat.setOutputPath(job, new Path(
  33.                 otherArgs[(otherArgs.length - 1)]));

  34.         System.exit(job.waitForCompletion(true) ? 0 : 1);
  35.     }

  36.     public static class IntCountReducer extends
  37.             Reducer<Text, IntWritable, Text, IntWritable> {
  38.         public void reduce(Text key, Iterable<IntWritable> values,
  39.                 Reducer<Text, IntWritable, Text, IntWritable>.Context context)
  40.                 throws IOException, InterruptedException {
  41.             int count = 0;
  42.             for (IntWritable value : values) {
  43.                 // 这里count累加value的值(就是1),这样就可以统计出总数出来了
  44.                 count = count + value.get();
  45.             }
  46.             context.write(key, new IntWritable(count));
  47.         }
  48.     }

  49.     public static class TokenizerMapper extends
  50.             Mapper<Object, Text, Text, IntWritable> {
  51.         public void map(Object key, Text value,
  52.                 Mapper<Object, Text, Text, IntWritable>.Context context)
  53.                 throws IOException, InterruptedException {
  54.             String line = value.toString();
  55.             String[] strarray = line.split(",");
  56.             Text status = new Text(strarray[10]);
  57.             // 取第11列的status的值作为map的key,因为只是统计count,所以使用一个常量1作为map的value就可以了
  58.             context.write(status, new IntWritable(1));
  59.         }
  60.     }

  61. }


2.6求每个object_type的id和,即select object_type,sum(id) from t group by object_type

新加入了LINESKIP,在map阶段用来统计出错的行;运行阶段加入了运行耗时

点击(此处)折叠或打开

  1. package exhadp;

  2. import java.io.IOException;
  3. import java.text.DateFormat;
  4. import java.text.SimpleDateFormat;
  5. import java.util.Date;

  6. import org.apache.hadoop.conf.Configuration;
  7. import org.apache.hadoop.conf.Configured;
  8. import org.apache.hadoop.fs.Path;
  9. import org.apache.hadoop.io.Text;
  10. import org.apache.hadoop.mapreduce.Job;
  11. import org.apache.hadoop.mapreduce.Mapper;
  12. import org.apache.hadoop.mapreduce.Reducer;
  13. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
  14. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
  15. import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
  16. import org.apache.hadoop.util.Tool;
  17. import org.apache.hadoop.util.ToolRunner;

  18. public class getsum extends Configured implements Tool {

  19.     enum Counter {
  20.         LINESKIP, // 出错的行
  21.     }

  22.     public int run(String[] args) throws Exception {
  23.         Configuration conf = new Configuration();

  24.         Job job = new Job(conf, "getsum"); // 任务名
  25.         job.setJarByClass(getsum.class); // 指定Class

  26.         FileInputFormat.addInputPath(job, new Path(args[0])); // 输入路径
  27.         FileOutputFormat.setOutputPath(job, new Path(args[1])); // 输出路径

  28.         job.setMapperClass(Map.class); // 调用上面Map类作为Map任务代码
  29.         job.setReducerClass(Reduce.class); // 调用上面Reduce类作为Reduce任务代码
  30.         job.setOutputFormatClass(TextOutputFormat.class);
  31.         job.setOutputKeyClass(Text.class); // 指定输出的KEY的格式
  32.         job.setOutputValueClass(Text.class); // 指定输出的VALUE的格式

  33.         job.waitForCompletion(true);

  34.         // 输出任务完成情况
  35.         System.out.println("任务名称:" + job.getJobName());
  36.         System.out.println("任务成功:" + (job.isSuccessful() ? "是" : "否"));
  37.         System.out.println("输入行数:"
  38.                 + job.getCounters()
  39.                         .findCounter("org.apache.hadoop.mapred.Task$Counter",
  40.                                 "MAP_INPUT_RECORDS").getValue());
  41.         System.out.println("输出行数:"
  42.                 + job.getCounters()
  43.                         .findCounter("org.apache.hadoop.mapred.Task$Counter",
  44.                                 "MAP_OUTPUT_RECORDS").getValue());
  45.         System.out.println("跳过的行:"
  46.                 + job.getCounters().findCounter(Counter.LINESKIP).getValue());

  47.         return job.isSuccessful() ? 0 : 1;
  48.     }

  49.     /**
  50.      * 设置系统说明 设置MapReduce任务
  51.      */
  52.     public static void main(String[] args) throws Exception {

  53.         // 判断参数个数是否正确
  54.         // 如果无参数运行则显示以作程序说明
  55.         if (args.length != 2) {
  56.             System.err.println("");
  57.             System.err.println("Usage: getsum < input path > < output path > ");
  58.             System.err
  59.                     .println("Example: hadoop jar exhadp.jar hdfs://localhost:9000/home/james/Test_2 hdfs://localhost:9000/home/james/output");
  60.             System.err.println("Counter:");
  61.             System.err.println("\t" + "LINESKIP" + "\t"
  62.                     + "Lines which are too short");
  63.             System.exit(-1);
  64.         }

  65.         // 记录开始时间
  66.         DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  67.         Date start = new Date();

  68.         // 运行任务
  69.         int res = ToolRunner.run(new Configuration(), new getsum(), args);

  70.         // 输出任务耗时
  71.         Date end = new Date();
  72.         float time = (float) ((end.getTime() - start.getTime()) / 60000.0);
  73.         System.out.println("任务开始:" + formatter.format(start));
  74.         System.out.println("任务结束:" + formatter.format(end));
  75.         System.out.println("任务耗时:" + String.valueOf(time) + " 分钟");

  76.         System.exit(res);
  77.     }

  78.     public static class Reduce extends Reducer<Text, Text, Text, Text> {
  79.         public void reduce(Text key, Iterable<Text> values, Context context)
  80.                 throws IOException, InterruptedException {

  81.             int sum = 0;

  82.             for (Text value : values) {
  83.                 sum = sum + Integer.parseInt(value.toString());
  84.             }

  85.             context.write(key, new Text(Integer.toString(sum)));
  86.         }
  87.     }

  88.     public static class Map extends Mapper<Object, Text, Text, Text> {
  89.         public void map(Object key, Text value, Context context)
  90.                 throws IOException, InterruptedException {
  91.             String line = value.toString(); // 读取源数据
  92.             String[] strarray = line.split(",");
  93.             try {
  94.                 Text status = new Text(strarray[6]);
  95.                 Text id = new Text(strarray[0]);

  96.                 context.write(status, id);
  97.             } catch (java.lang.ArrayIndexOutOfBoundsException e) {
  98.                 context.getCounter(Counter.LINESKIP).increment(1); // 出错令计数器+1
  99.                 return;
  100.             }
  101.         }
  102.     }
  103. }


2.7导出并运行jar包

导出jar包







将生成的
jar文件复制到hadoop集群中即可运行:

[grid@dehadp01 ~]$ hadoop jar exhadp.jar getsum TEST_OBJECTS/part-m-00000 getsum_out

15/07/30 16:30:01 WARN mapreduce.JobSubmitter: Hadoop command-line option parsing not performed. Implement the Tool interface and execute your application with ToolRunner to remedy this.

15/07/30 16:30:01 INFO input.FileInputFormat: Total input paths to process : 1

15/07/30 16:30:01 INFO mapreduce.JobSubmitter: number of splits:1

15/07/30 16:30:02 INFO mapreduce.JobSubmitter: Submitting tokens for job: job_1437633633589_0067

15/07/30 16:30:02 INFO impl.YarnClientImpl: Submitted application application_1437633633589_0067

15/07/30 16:30:02 INFO mapreduce.Job: The url to track the job: http://dehadp01:8088/proxy/application_1437633633589_0067/

15/07/30 16:30:02 INFO mapreduce.Job: Running job: job_1437633633589_0067

15/07/30 16:30:11 INFO mapreduce.Job: Job job_1437633633589_0067 running in uber mode : false

15/07/30 16:30:11 INFO mapreduce.Job:  map 0% reduce 0%

15/07/30 16:30:20 INFO mapreduce.Job:  map 100% reduce 0%

15/07/30 16:30:29 INFO mapreduce.Job:  map 100% reduce 100%

15/07/30 16:30:29 INFO mapreduce.Job: Job job_1437633633589_0067 completed successfully

15/07/30 16:30:29 INFO mapreduce.Job: Counters: 49

File System Counters

FILE: Number of bytes read=1253658

FILE: Number of bytes written=2723009

FILE: Number of read operations=0

FILE: Number of large read operations=0

FILE: Number of write operations=0

HDFS: Number of bytes read=10921559

HDFS: Number of bytes written=785

HDFS: Number of read operations=6

HDFS: Number of large read operations=0

HDFS: Number of write operations=2

Job Counters 

Launched map tasks=1

Launched reduce tasks=1

Data-local map tasks=1

Total time spent by all maps in occupied slots (ms)=6421

Total time spent by all reduces in occupied slots (ms)=6858

Total time spent by all map tasks (ms)=6421

Total time spent by all reduce tasks (ms)=6858

Total vcore-seconds taken by all map tasks=6421

Total vcore-seconds taken by all reduce tasks=6858

Total megabyte-seconds taken by all map tasks=6575104

Total megabyte-seconds taken by all reduce tasks=7022592

Map-Reduce Framework

Map input records=75942

Map output records=75942

Map output bytes=1101768

Map output materialized bytes=1253658

Input split bytes=115

Combine input records=0

Combine output records=0

Reduce input groups=44

Reduce shuffle bytes=1253658

Reduce input records=75942

Reduce output records=44

Spilled Records=151884

Shuffled Maps =1

Failed Shuffles=0

Merged Map outputs=1

GC time elapsed (ms)=105

CPU time spent (ms)=8210

Physical memory (bytes) snapshot=444616704

Virtual memory (bytes) snapshot=2427170816

Total committed heap usage (bytes)=306708480

Shuffle Errors

BAD_ID=0

CONNECTION=0

IO_ERROR=0

WRONG_LENGTH=0

WRONG_MAP=0

WRONG_REDUCE=0

File Input Format Counters 

Bytes Read=10921444

File Output Format Counters 

Bytes Written=785

任务名称:getsum

任务成功:是

输入行数:75942

输出行数:75942

跳过的行:0

任务开始:2015-07-30 16:29:58

任务结束:2015-07-30 16:30:29

任务耗时:0.52346665 分钟

[grid@dehadp01 ~]$ hadoop fs -cat getsum_out/part-r-00000

CLUSTER 2607

CONSUMER GROUP 309547

CONTEXT 233362

DESTINATION 24817

DIRECTORY 84148

EDITION 99

EVALUATION CONTEXT 342371

FUNCTION 14181134

INDEX 256715660

INDEX PARTITION 18627058

INDEXTYPE 524538

JAVA CLASS 867243753

JAVA DATA 17401769

JAVA RESOURCE 44179866

JAVA SOURCE 111708

JOB 315526

JOB CLASS 220990

LIBRARY 4042643

LOB 68668545

LOB PARTITION 11075

MATERIALIZED VIEW 68788

OPERATOR 2573501

PACKAGE 52912299

PACKAGE BODY 52093978

PROCEDURE 4944329

PROGRAM 245410

QUEUE 1207189

RESOURCE PLAN 123925

RULE 12864

RULE SET 471244

SCHEDULE 37694

SCHEDULER GROUP 50096

SEQUENCE 6181131

SYNONYM 993156532

TABLE 124894005

TABLE PARTITION 75556978

TABLE SUBPARTITION 281680

TRIGGER 43385559

TYPE 110249150

TYPE BODY 9475369

UNDEFINED 136498

VIEW 109084203

WINDOW 112671

XML SCHEMA 3135344


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/20777547/viewspace-1760222/ ,如需转载,请注明出处,否则将追究法律责任。

下一篇: 学习HBASE
请登录后发表评论 登录
全部评论

注册时间:2013-10-17

  • 博文量
    16
  • 访问量
    127043