MapReduce-定制Partitioner-求文件奇偶数行之和

来源:互联网 发布:nginx配置文件server 编辑:程序博客网 时间:2024/05/16 23:35
这篇博客说明Partioner定制的问题,partion发生在map阶段的最后,会先调用job.setPartitionerClass对这个List进行分区,每个分区映射到一个reducer。每个分区内又调用job.setSortComparatorClass设置的key比较函数类排序。前面的几篇博客的实例都是用的一个reducer,这个实例的完成将使用二个reducer的情况,至于多reducer的测试将在全局排序的实例中演示。
下面是本篇博客的实例的需求:
测试数据:
324
654
23
34
78
2
756
134
32
需求:求出数据的奇数行和偶数行之和
这里主要是用到定制partitioner,以下是如何自定义分区函数类。
只要继承Partitioner<T,T> 
public class MyPartitioner extends Partitioner<T,T>
然后去实现其中的getPartition()方法就行了,在其中完成分区的逻辑以及一些对于需求的对象key-value对的修改
下面为实现代码:

自定义partitioner:

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. import org.apache.hadoop.io.IntWritable;  
  2. import org.apache.hadoop.io.LongWritable;  
  3. import org.apache.hadoop.mapreduce.Partitioner;  
  4.   
  5. public class MyPartitioner extends Partitioner<LongWritable, IntWritable> {  
  6.     @Override  
  7.     public int getPartition(LongWritable key, IntWritable value, int arg2) {  
  8.         /** 
  9.          * 根据行号进行分区,把行号为的偶数的分区到0号reduce 
  10.          * 把行号为奇数的分区到1号reduce,并把key的值设置为0或1 
  11.          * 目的是为了在进入reduce时奇数和偶数能被分别放到同一个 
  12.          * 迭代器中以便求和操作 
  13.          */  
  14.         if( key.get() % 2 == 0) {  
  15.             key.set(0);  
  16.             return 0;  
  17.         } else {  
  18.             key.set(1);  
  19.             return 1;  
  20.         }  
  21.     }  
  22. }  
map阶段:
[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. import java.io.IOException;  
  2. import org.apache.hadoop.io.IntWritable;  
  3. import org.apache.hadoop.io.LongWritable;  
  4. import org.apache.hadoop.io.Text;  
  5. import org.apache.hadoop.mapreduce.Mapper;  
  6.   
  7.   
  8. public class MyMapper extends Mapper<LongWritable, Text, LongWritable, IntWritable> {  
  9.   
  10.   
  11.     private long lineNum = 0;  
  12.     private LongWritable okey = new LongWritable();  
  13.     @Override  
  14.     protected void map(LongWritable key, Text value, Context context)  
  15.             throws IOException, InterruptedException {  
  16.         lineNum ++;  
  17.         okey.set(lineNum);  
  18.         /** 
  19.          * 输出行号作为key,并把行的值作为value,这里只是简单的说明的patitioner的定制 
  20.          * 不考虑多mapper情况下行号控制,这里只关注partitioner的使用就行 
  21.          */  
  22.         context.write(okey, new IntWritable(Integer.parseInt(value.toString())));  
  23.     }  
  24. }  
reduce阶段:
[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. import java.io.IOException;  
  2. import org.apache.hadoop.io.IntWritable;  
  3. import org.apache.hadoop.io.LongWritable;  
  4. import org.apache.hadoop.io.Text;  
  5. import org.apache.hadoop.mapreduce.Reducer;  
  6.   
  7. public class MyReducer extends Reducer<LongWritable, IntWritable, Text, IntWritable> {  
  8.   
  9.     @Override  
  10.     protected void reduce(LongWritable key, Iterable<IntWritable> value, Context context)  
  11.             throws IOException, InterruptedException {  
  12.         int sum = 0;  
  13.         for( IntWritable val : value) {  
  14.             sum += val.get();  
  15.         }  
  16.         if( key.get() == 0 ) {  
  17.             context.write(new Text("偶数行之和为:"), new IntWritable(sum));  
  18.         } else if ( key.get() == 1) {  
  19.             context.write(new Text("奇数行之和为:"), new IntWritable(sum));  
  20.         }  
  21.     }  
  22. }  
启动函数:
[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. import org.apache.hadoop.conf.Configuration;  
  2. import org.apache.hadoop.fs.FileSystem;  
  3. import org.apache.hadoop.fs.Path;  
  4. import org.apache.hadoop.io.IntWritable;  
  5. import org.apache.hadoop.io.LongWritable;  
  6. import org.apache.hadoop.io.Text;  
  7. import org.apache.hadoop.mapreduce.Job;  
  8. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;  
  9. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;  
  10.   
  11. public class JobMain {  
  12.     public static void main(String[] args) throws Exception {  
  13.         Configuration configuration = new Configuration();  
  14.         Job job = new Job(configuration, "partitioner-job");  
  15.         job.setJarByClass(JobMain.class);  
  16.         job.setMapperClass(MyMapper.class);  
  17.         job.setMapOutputKeyClass(LongWritable.class);  
  18.         job.setMapOutputValueClass(IntWritable.class);  
  19.         //设置自定义的Partitioner对map输出进行分区  
  20.         job.setPartitionerClass(MyPartitioner.class);  
  21.         job.setReducerClass(MyReducer.class);  
  22.         job.setOutputKeyClass(Text.class);  
  23.         job.setOutputValueClass(IntWritable.class);  
  24.         //设置job的reducer的个数为2  
  25.         job.setNumReduceTasks(2);  
  26.         FileInputFormat.addInputPath(job, new Path(args[0]));  
  27.         Path outputDir = new Path(args[1]);  
  28.         FileSystem fs = FileSystem.get(configuration);  
  29.         if( fs.exists(outputDir)) {  
  30.             fs.delete(outputDir ,true);  
  31.         }  
  32.         FileOutputFormat.setOutputPath(job, outputDir);  
  33.         System.exit(job.waitForCompletion(true) ? 01);  
  34.     }  
  35. }  
运行结果:


结论:
为了说明某一个知识点的作用,博客都是以尽可以只涉及要讲的点的运行,到后面会有一些综合一点的,一些点结合起来的例子,mapreduce框架很灵活,可以定制的功能也很多,后面会一一的说明,比如自定义InputFormat、RecordReader、OutputFormat、RecordWriter,后面还会说明难一点的实例--使用mapreduce处理xml以及json格式的文件来分别说明这些扩展点。对于大文件被分成多个spilt而用多个map计算奇偶数行之和,参见《MapReduce-定制Partitioner-使用NLineInputFormat处理大文件-求文件奇偶数行之和》
0 0
原创粉丝点击