Hadoop 复习整理(MapReduce)

什么是MapReduce?

主要由Map和Reduce两部分组成。
Reduce阶段在Map阶段执行结束之后执行。
Map阶段的输出结果作为Reduce阶段的输入结果。
Reduce阶段的输入结果对应于多个Map的输出结果。
Reduce阶段计算最终结果并将结果输出。

输入数据:一系列key/value对。
用户实现两个函数,map和reduce。
Map(k,v)list(k1,v1)
Reduce(k,list(v1)) v2
(k1,v1)是中间key/value的结果对。
Output:一系列的(k2,v2)对。  

package com.neu.mapreduce.topK;

import java.io.IOException;
import java.util.TreeMap;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.DoubleWritable;
import org.apache.hadoop.io.NullWritable;
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;

import com.neu.mapreduce.util.FanData;
import com.neu.mapreduce.util.HDFSUtils;

public class TopK {

   public static class TopKMapper extends Mapper<Object, Text, NullWritable, DoubleWritable> {

      private FanData fanData = new FanData();
      
      private static final int K = 10;
      
      private TreeMap<Double, Double> tm = new TreeMap<Double, Double>();
      
      @Override
      protected void map(Object key,Text value, Context context)
            throws IOException, InterruptedException {
         fanData.getInstance(value.toString());
         double windSpeed = Double.parseDouble(fanData.getWindSpeed());
         tm.put(windSpeed, windSpeed);
         if(tm.size() > K) {
            tm.remove(tm.firstKey());
         }
      }
      
      @Override
      protected void cleanup(Context context)
            throws IOException, InterruptedException {
         super.cleanup(context);
         for(Double ws : tm.values()) {
            context.write(NullWritable.get(), new DoubleWritable(ws));
         }
      }
      
   }
   
   public static class TopKReducer extends Reducer<NullWritable, DoubleWritable, NullWritable, DoubleWritable> {

      private static final int K = 10;
      
      private TreeMap<Double, Double> tm = new TreeMap<Double, Double>();
      
      @Override
      protected void reduce(NullWritable key,Iterable<DoubleWritable> values, Context context)
            throws IOException, InterruptedException {
         for(DoubleWritable ws : values) {
            tm.put(ws.get(), ws.get());
            if(tm.size() > K) {
               tm.remove(tm.firstKey());
            }
         }
         for(Double ws : tm.values()) {
            context.write(NullWritable.get(), new DoubleWritable(ws));
         }
      }
      
   }
   
   public static void main(String[] args) throws Exception{
      Configuration conf = new Configuration();
      HDFSUtils hdfs = new HDFSUtils(conf);
      hdfs.deleteDir(args[1]);
      Job job = Job.getInstance();
      job.setJarByClass(TopK.class);
      job.setMapperClass(TopKMapper.class);
      job.setMapOutputKeyClass(NullWritable.class);
      job.setMapOutputValueClass(DoubleWritable.class);
      job.setReducerClass(TopKReducer.class);
      job.setOutputKeyClass(NullWritable.class);
      job.setOutputValueClass(DoubleWritable.class);
      FileInputFormat.addInputPath(job, new Path(args[0]));
      FileOutputFormat.setOutputPath(job, new Path(args[1]));
      System.exit(job.waitForCompletion(true)? 0 : 1);
   }
   
}

1.数据分片:等长的数据块,每个分片对应一个map任务。分片的大小很大程度影响了map执行的效率。建议分片大小和hdfs数据块大小相同,好处是节省网络开销。
2.Map任务结果并非保存在hdfs:临时数据。Map失败后会在其他节点上启动map。
3.Reduce的任务数量并非由输入数据大小指定,而事实上是独立指定的。Map:reduce=n:m
4.Partition:map输出结果会根据reduce个数进行分区,默认是hash函数来分区,也可以自定义(partition函数)。
5.Shuffle:map和reduce之间的数据流。每个reduce的输入来自于多个map任务的输出。在这个阶段,参数调优对job的运行时间有很大的影响。是奇迹发生的地方。

shuffle 是什么?过程?
在MapReduce过程中需要将各个节点上的同一类数据汇集到一个节点进行计算。把这些分布在不同节点的数据按照一定规则聚集到一起的过程,就称之为shuffle(Shuffle是Map和Reduce之间的操作,Shuffle 过程本质上就是将 Map 端获得的数据使用分区器进行划分,并将数据发送给对应的 Reducer 的过程)。


 

猜你喜欢

转载自blog.csdn.net/qq_36290948/article/details/87087024