剖析MapReduce程序

12月8日 第18天

1.典型MapReduce程序的每个阶段



2.hadoop的数据类型

      MapReduce框架提供了一种序列化键/值对的方法,只有那些支持这种序列化的类能够在这个框架中充当键或值。
      也可以自定义数据类型,只要实现了Writable或WritableComparable接口,WritableComparable接口是Writable和java.long.Comparable接口的组合。实现Writable接口的类可以是值,实现WritableComparable接口的类可以是键也可以是值。

 BlooleanWritable 标准布尔变量的封装
 ByteWritable 单字节数的封装
 DoubleWritable 双字节数的封装
 FloatWritable 浮点数的封装
 IntWritable 整数的封装
 LongWritable Long的封装
 Text 使用UT8格式的文本封装
 NullWritable 无键值时的站位符
表1键/值对常使用的数据类型列表(都实现WritableComparable接口)

自定义数据类型代码:
package org.apache.hadoop.examples;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;

import org.apache.hadoop.io.WritableComparable;

public class Edge implements WritableComparable{

    privateString departureNode;
    privateStringarrivalNode;   
   
    //departureNode的get方法
    publicString getDepartureNode() {
       returndepartureNode;
    }

    //如何读入数据
   @Override
    public voidreadFields(DataInput in) throws IOException {
      departureNode = in.readUTF();
       arrivalNode= in.readUTF();
    }

    //如何写出数据
   @Override
    public voidwrite(DataOutput out) throws IOException {
      out.writeUTF(departureNode);
      out.writeUTF(arrivalNode);
    }

   //定义数据排序
   @Override
    public intcompareTo(Edge o) {
       //三目运算符:表达式1真返回表达式2,假返回表达式3
       return(departureNode.compareTo(o.departureNode) != 0) ?departureNode.compareTo(o.departureNode) :arrivalNode.compareTo(o.arrivalNode);
    }
}


3.Mapper

      一个类要作为Mapper,需要继承MapReduceBase基类,实现Mapper接口。
      voidconfigure(JobConf conf) —— 处理数据前调用,提取xml文件和主类中的参数
      void close()—— 最后一个操作,关闭数据库,打开文件等
      Mapper的形式为Mapper用于处理一个单独的键/值对。
       void map(
           K1 key,  //键值对(K1,V1)
           V1 value,
           OutputCollector output,  //生成键值对(K2,V2)的列表,output接受这个映射过程的输出
           Reporter reporter  //提供记录,形成任务进度
       )throws IOException


 IdentityMapper实现Mapper,将输入直接映射到输出
 InverseMapper 实现Mapper,翻转键/值对
 RegexMapper 实现Mapper,为每个常规表达式的匹配生成一个(match,1)对
 TokenCountMapper 实现Mapper,当输入的值为分词时,生成一个(token,1)对
表2常用的hadoop预定义的Mapper实现

4.Reducer

      和Mapper一样,必须先在MapReduce基类上扩展,实现接口Reducer,使其具有如下的单一方法:
       void reduce(
           K2 key,  //给定的键
           Iterator values,  //迭代出与键相关的值
           OutputCollector output,  //生成(K3,V3),用output接收、写入输出文件
           Reporter reporter  //reduce相关信息记录,形成任务进度
       )throws IOException


      流程为:各个Mapper输出→reducer接收→按键排序→相同键值归并→reduce()

 IdentityReducer 实现Reducer,将输入直接映射到输出
 LongSumReducer实现,计算与给定键相对应的所有值的和
表3常用的hadoop预定义的Reducer实现

5.Partitioner

      重定向Mapper输出(将Mapper的结果输出给不同的reducer)。
      初次使用MapReduce的程序猿通常有一个误解,以为仅需使用一个reducer,但是,当使用多个reducer时,我们需要采取一些办法来确定mapper应该把键/值对输出给谁,这时候就需要定制partitioner了。
      定制partitioner方法:
              ①实现Partitioner接口(implements Partitioner)
              ②实现configure(),将hadoop对作业的配置应用在patitioner上
              ③实现getPartition(),返回0和reduce任务数之间的整数,指向键/值对将要发送到的reducer
实现定制partitioner代码:
package org.apache.hadoop.examples;

import org.apache.hadoop.io.Writable;
import org.apache.hadoop.mapred.JobConf;
import org.apache.hadoop.mapred.Partitioner;

public class EdgePartitioner implements Partitioner{

   @Override
    public voidconfigure(JobConf conf) {}

   @Override
    public intgetPartition(Edge key, Writable value, int numPartitions) {
       returnkey.getDepartureNode().hashCode() % numPartitions;
    }
}

6.Combiner
 
      本地reducer(略)。

7.使用预定义的mapper和reducer类完成单词计数

package org.apache.hadoop.examples;

import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.mapred.FileInputFormat;
import org.apache.hadoop.mapred.FileOutputFormat;
import org.apache.hadoop.mapred.JobClient;
import org.apache.hadoop.mapred.JobConf;
import org.apache.hadoop.mapred.lib.LongSumReducer;
import org.apache.hadoop.mapred.lib.TokenCountMapper;

importcom.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider.Text;

public class WordCount2 {

    publicstatic void main(String[] args){
       JobClientclient = new JobClient();
       JobConf conf= new JobConf(WordCount2.class);
      
      FileInputFormat.addInputPath(conf, new Path(args[0]));
      FileOutputFormat.setOutputPath(conf, new Path(args[1]));
      
      conf.setOutputKeyClass(Text.class);
      conf.setOutputValueClass(LongWritable.class);
       //使用预定义的类TokenCountMapper当输入的值为分词时,生成一个(token,1)对
      conf.setMapperClass(TokenCountMapper.class);
       //预定义的类LongSumReducer计算与给定健相对应的所有值和
      conf.setCombinerClass(LongSumReducer.class);
      conf.setReducerClass(LongSumReducer.class);
      
      client.setConf(conf);
      
       try{
         JobClient.runJob(conf);
      }catch(Exception e){
         e.printStackTrace();
       }
    }
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值