Hoodoop-MapReduce学习

基本介绍

一.概念
1.MapReduce是Hadoop提供的一套进行分布式计算机制
2.MapReduce是Doug Cutting根据Google的论文来仿照实现的
3.MapReduce会将整个计算过程拆分为2个阶段:Map阶段和Reduce阶段。在Map阶段,用户需要考虑对数据进行规整和映射;在Reduce阶段,用户需要考虑对数据进行最后的规约

二.特点
1.优点
a.易于编程:MapReduce提供了相对简单的编程模型。这就保证MapReduce相对易于学习。用户在使用的时候,只需要实现一些接口或者去继承一些类,覆盖需要实现的逻辑,即可实现分布式计算
b.具有良好的可扩展性:如果当前集群的性能不够,那么MapReduce能够轻易的通过增加节点数量的方式来提高集群性能
c.高容错性:当某一个节点产生故障的时候,MapReduce会自动的将这个节点上的计算任务进行转移而整个过程不需要用户手动参与
d.适合于大量数据的计算,尤其是PB级别以上的数据,因此MapReduce更适合于离线计算
2.缺点:
a.不适合于实时处理:MapReduce要求处理的数据是静态的,实时的特点在于数据池是动态的
b.不擅长流式计算:MapReduce的允许效率相对较低,在处理流式计算的时候,效率更低
c.不擅长DAG(有向图)运算:如果希望把上一个MapReduce的运行结果作为下一个MapReduce的输入数据,那么需要手动使用工作流进行调度,而MapReduce本身没有这种调度功能

三.入门案例
1.案例:统计文件中每一个非空字符串出现的次数
在这里插入图片描述

import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import java.io.IOException;
//用于完成Map阶段
//在MapReduce中,要求被处理的数据能够被序列化
//MapReduce提供了一套序列化机制
//KEYIN - 输入的键的类型。如果不指定,那么默认情况下,表示行的字节偏移量
//VALUEIN -输入的值的类型,如果不指定,那么默认情况下,表示的读取到的一行数据
//KEYOUT - 输出的键的类型。当前案例中,输出的键表示的是字符
//VALUEOUT - 输出的值的类型。当前案列中,输出的值表示的是次数
public class CharCountMapper extends Mapper<LongWritable, Text, Text, LongWritable>{
   
  private final LongWritable once = new LongWritable(1);

  //覆盖map方法,将处理逻辑写到这个方法中
  //key:键。表示的是行的字节偏移量
  //value:值。表示读取到的一行数据
  //context:配置参数
  @Override
  protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException{
   
    //将一行数据中的字符拆分出来
    char[] cs = value.toString().toCharArray();
    //假设数据时hello,那么拆分出来的数据中包含的就是{'h','e','l','l','o'}
    //可以写出h:1 e:1 l:2 o:1
    //可以写出h:1 e:1 l:1 l:1 o:1
    for (char c : cs) {
   
      context.write(new Text(c+""), once);
    }
  }
}

import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
import java.io.IOException;
//KEYIN,VALUEIN - 输入的键值类型。Reducer的数据从Mapper来的,所以Mapper的输出就是Reducer的输入
//KEYOUT,VALUEOUT - 输出的键值类型。当前案列中,要输出每一个字符对应的总次数
public class CharCountReducer extends Reducer<Text, LongWritable, Text, LongWritable> {
   

  //覆盖reduce方法,将计算逻辑写到这个方法中
  //key:键。当前案列中,键是字符
  //values:值。当前案例中,值是次数的集合对应的迭代器
  //context:配置参数
  @Override
  protected void reduce(Text key, Iterable<LongWritable> values,Contxt context) throw IOException, InterruptedException{
   
    //key = 'a'
    //values ={1,1,1,1,1,1...}
    //定义变量来记录总次数
    int sum = 0for(LongWritable value : values){
   
      sum +=value.get();
    }
    context.write(key, new LongWritable(sum));
  }
}

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import java.io.IOException;
public class CharCountDriver {
   
  public static void main(String[] args) throw IOException{
   
    //构建环境变量
    Configuration conf = new Configuration();
    //构建任务
    Job job = Job.getInstance(conf);
    
    //设置入口类
    job.setJarByClass(CharCountDriver.class);
    //设置Mapper类
    job.setMapperClass(CharCountReducer.class);
    //设置Reducer类
    job.setReducerClass(CharCountReducer.class);

    //设置Mapper的输出类型
    job.setMapOutputKeyClass(Text.class);
    job.setMapOutputValueClass(LongWritable.class);
    
    //设置Reducer的输出类型
    job.setOutputKeyClass(Text.class);
    job.setOutputValueClass(LongWritable.class);

    //设置输入路径
    FileInputFormat.addInputPath(job, new Path("hdfs://hadoop01:9000/text/characters.txt"));
    //设置输出路径 - 要求输出路径必须不存在
    FileOutputFormat.addOutputPath(job, new Path("hdfs://hadoop01:9000/result/char_count.txt"));

    //提交任务
    job.waitForCompletion(true);
    
  }
}

组件

一.序列化
1.在MapReduce中,要求被处理的数据能够被序列化。MapReduce提供了单独的序列化机制 - MapReduce底层的序列化机制是基于AVRO实现的。为了方便操作,在AVRO的基础上,MapReduce提供了更简单的序列化形式 - 只需要让被序列化的对象对应的类实现Writeable接口,覆盖其中的write和readFields方法
2.MapReduce针对常见类型提供了基本的序列化类
在这里插入图片描述
3.在MapReduce中,要求被序列化的对象对应的类中必须提供无参构造
4.在MapReduce中,要求被序列的对象的属性值不能为null
5.案例:统计一个人花费的上行流量和下行流量

/*
 手机       地区   姓名 上行流量 下行流量
 1860000000  bj    zs    4252    5236
 1860000001  bj    ls    5264    2152
 1860000002  sh    wl    5256    3256
 1860000000  bj    zd    9252    9236
 1860000001  bj    ll    5864    4152
 1860000002  sh    ww    5256    6256
*/
public class Flow implements Writable{
   
  private int upFlow;
  private int downFlow;
  public int getUpFlow(){
   return upFlow;}
  public void setDownFlow(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.writeInt(getUpFlow());
    out.writeInt(getDownFlow());
  }
  @Override
  public void readFields(DataInput in) throws IOException{
   
    setUpFlow(in.readInt());
    setDownFlow(in.readInt());
  }
}

public class SerialFlowMapper extends Mapper<LongWritable, Text, Text, Flow>{
   
  @Override
  protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException{
   
    //1860000000  bj    zs    4252    5236
    //拆分字段
    String[] arr = value.toString().split(" ");
    //封装对象
    Flow f = new Flow();
    f.setUpFlow(Integer.parseInt(arr[3]));
    f.setDownFlow(Integer.parseInt(arr[4]));
    contex
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值