Hadoop之mapreduce -- WrodCount案例以及各种概念

文章目录

  • 一、MapReduce的优缺点
  • 二、MapReduce案例--WordCount
    • 1、导包
    • 2、Mapper方法
    • 3、Partitioner方法(自定义分区器)
    • 4、reducer方法
    • 5、driver(main方法)
    • 6、Writable(手机流量统计案例的实体类)
  • 三、关于片和块
    • 1、什么是片,什么是块?
    • 2、mapreduce 启动多少个MapTask任务?
  • 四、MapReduce的原理
  • 五、Shuffle 过程
  • 六、环形缓冲区
  • 七、Combiner


一、MapReduce的优缺点

优点
– 1、易于编程
– 2、良好的扩展性
– 3、高容错性
– 4、非常适合大数据集的计算
缺点
– 1、不适合做实时计算
– 2、不适合做流式计算
– 3、不适合做有向图(DAG)计算
多个应用程序之间有依赖关系,后一个程序需要依赖前面的程序的结果。这种场景就称之为有向图

二、MapReduce案例–WordCount

1、导包

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

2、Mapper方法

class WordCountMapper extends Mapper<LongWritable, Text,Text, IntWritable> {
    @Override
    // key 值 指的是行偏移量
    // value 指的是 这一行数据
    protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, IntWritable>.Context context) throws IOException, InterruptedException {
        String line = value.toString();
        String[] arr = line.split("\\s+");
        for (String word : arr) {
            context.write(new Text(word),new IntWritable(1));
        }
    }
}

3、Partitioner方法(自定义分区器)

//Map任务 --> Partitioner  --> Reducer
class WordCountPartitioner extends Partitioner<Text, IntWritable> {
    public int getPartition(Text text, IntWritable intWritable, int i) {
        String word = text.toString();
        char c = word.charAt(0);
        if (c >= 'a' && c <= 'p'){
            return 0;
        }else if (c >= 'q' && c <= 'z'){
            return 1;
        }else {
            return 2;
        }
    }
}

4、reducer方法

class WordCountReducer extends Reducer<Text, IntWritable,Text,IntWritable> {
    @Override
    protected void reduce(Text key, Iterable<IntWritable> values, Reducer<Text, IntWritable, Text, IntWritable>.Context context) throws IOException, InterruptedException {
        int sum = 0;
        for (IntWritable value : values) {
            sum += value.get();
        }
        context.write(key, new IntWritable(sum));
    }
}

5、driver(main方法)

public class WordCountDriver {
    public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException {
        Configuration conf = new Configuration();
        // 使用本地的文件系统,而不是hdfs
        conf.set("fs.defaultFS","file:///");
        // 使用本地的资源(CPU,内存等), 也可以使用yarn平台跑任务
        conf.set("mapreduce.framework.name","local");
        Job job = Job.getInstance(conf,"单词统计");
        // 指定 map
        job.setMapperClass(WordCountMapper.class);
        //指定分区器
        job.setPartitionerClass(WordCountPartitioner.class);
        // 设置reduceTask的数量
        // reduce的数量决定了reduceTask的任务数量,每一个任务,结束后都会产生一个文件 part-r-xxxxx
        job.setNumReduceTasks(3);
        //指定reducer
        job.setReducerClass(WordCountReducer.class);

        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(IntWritable.class);

        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);

        FileInputFormat.setInputPaths(job,new Path("./mr01/input"));
        FileOutputFormat.setOutputPath(job,new Path("./mr01/output"));
        boolean result = job.waitForCompletion(true);
        System.exit(result?0:-1);
    }
}

6、Writable(手机流量统计案例的实体类)

public class PhoneFlowWritable implements Writable {
    private String phone;
    private int upFlow;
    private int downFlow;
    // 此处需要指定一个空参数的构造方法,否则报错:
    // java.lang.NoSuchMethodException: com.bigdata.phoneflow.PhoneFlowWritable.()
    public PhoneFlowWritable() {
    }
    public PhoneFlowWritable(String phone, int upFlow, int downFlow) {
        this.phone = phone;
        this.upFlow = upFlow;
        this.downFlow = downFlow;
    }
    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }
    public int getUpFlow() {
        return upFlow;
    }
    public void setUpFlow(int upFlow) {
        this.upFlow = upFlow;
    }
    public int getDownFlow() {
        return downFlow;
    }
    public void setDownFlow(int downFlow) {
        this.downFlow = downFlow;
    }
    @Override
    public void write(DataOutput out) throws IOException {
        out.writeUTF(phone);
        out.writeInt(upFlow);
        out.writeInt(downFlow);
    }
    @Override
    public void readFields(DataInput in) throws IOException {
        phone =  in.readUTF();
        upFlow = in.readInt();
        downFlow = in.readInt();
    }
}

三、关于片和块

1、什么是片,什么是块?

块是物理概念,片是逻辑概念。一般片 = 块,但是到最后一次的时候,有可能片> 块,但是绝对不能超过块的1.1倍。

2、mapreduce 启动多少个MapTask任务?

跟片有关系,有多少个片,就启动多少个map任务。跟块儿无关。

四、MapReduce的原理

AppMaster: 整个Job任务的核心协调工具
MapTask: 主要用于Map任务的执行
ReduceTask: 主要用于Reduce任务的执行

一个任务提交 --> AppMaster–> 根据切片的数量统计出需要多少个MapTask任务 --> 向ResourceManager(Yarn平台的老大)索要资源 --> 执行Map任务,先读取一个分片的数据,传递给map方法。–> map 方法不断的溢写 --> reduce 方法 --> 将统计的结果存放在磁盘上。

五、Shuffle 过程

MapReduce的Shuffle过程指的是MapTask的后半程,以及ReduceTask的前半程,共同组成的。 从MapTask中的map方法结束,到ReduceTask中的reduce方法开始,这个中间的部分就是Shuffle。是MapReduce的核心,心脏。

六、环形缓冲区

1、环形缓冲区,其实是一个数组,将数组分为两部分,分割的这个点就称之为轴心。
2、存储KV真实数据,是顺时针存储
3、每一个KV真实数据都有对应的元数据,元数据是逆时针存储。
4、当两者数据占用空间达到80%的时候,需要清理数组,清理完之后,轴心发生了变化

七、Combiner

Combiner其实就是运行在mapTask中的reducer。 Reducer其实就是合并代码的。Combiner是作用在Map端的。
Combiner 只能用于对统计结果没有影响的场景下。
一般只用于统计之和,统计最大值最小值的场景下。统计平均值等情况是不能用的。

你可能感兴趣的:(hadoop,mapreduce,大数据)