读书笔记2:Hadoop组件-(2)剖析MapReduce程序

本文深入剖析了Hadoop MapReduce的工作原理,介绍了数据类型、Mapper、Reducer、Partitioner和Combiner的功能及实现方式,并展示了如何使用预定义的Mapper和Reducer简化编程。

 

3,剖析 MapReduce 程序

<1>hadoop的数据类型

实现Writable 接口额类可以是值,而实现 WritableComparable 接口的类既可以是键也可以是值。

以下这些是常用的数据类型,均用于实现WritableComparable 借口:

BooleanWritable

ByteWritable

DoubleWritable

FloatWritable

IntWritable

LongWritable

Text 使用UTF8 格式的文本封装

NullWritable 无键值时的占位符

也可以自定义数据类型,但要实现Writable 接口或者 WritableComparable 接口。

<2>Mapper

一个类要作为mapper ,需要继承 MapReduceBase 基类和实现 Mapper 借口。

mapper和 reducer 的基类均为 MapReduceBase ,它包含类的构造和解构方法:

void configure(JobConf job);该函数提取 XML 配置文件或者应用程序主类中的参数,在数据处理之前调用该函。

void close();作为 map 任务结束前的最后一个操作,该函数完成所有的结尾工作,如关闭数据库、打开文件等。

Mapper借口负责数据处理阶段,采用的形式是 Mapper<K1,V1,K2,V2>java 泛型,键类和值类分别实现 WritableComparableWritable 借口。

Mapper只有一个方法 map 用于处理一个单独的键值对。

void map(K1 key,V1 value,OutputCollector<K2,V2> output,Reporter reporter)

该函数处理一个给定的键值对(K1,V1), 生成一个键值对 (K2,V2) 的列表。

OutputCollector接收这个映射过程的输入。

Reporter 可提供对 Mapper 相关附加信息的记录,形成任务进度。

 

Hadoop预定义的 Mapper 的实现 :

IdentityMapper<K,V>

实现Mapper<K,V,K,V> 就输入直接映射到输出

InverseMapper<K,V>

实现Mapper<K,V,K,V> 发转键值对

RegexMapper<K>

实现Mapper<K,Text,Text,LongWritable>, 为每个常规表达式的匹配项生成一个 (mathc,1)

TokenCountMapper<K>

实现Mapper<K,Text,Text,LongWritable>, 当输入的值为分词时,生成一个 (token,1)

<3>Reducer

reducer的实现也必须继承 MapReduceBase 类和实现 Reducer 接口。

Reducer接口只有一个方法,及时 reduce:

Void reduce (K2,key,Iterator<V2> values,OutputCollector<K3,V3> output,Reporter r)

Reducer任务接收来自各个 mapper 的输出时,按照键对输入数据进行排序,并将相同的键的值归并,然后调用 reduce 函数,并通过迭代处理那些与指定键相关联的值,生成一个列表 <K3,V3>

OutputCollector接收 reduce 阶段的输出,并写入输出文件。

Reporter 可提供对 Mapper 相关附加信息的记录,形成任务进度。

 

Hadoop预定义的 Reducer 的实现 :

IdentityReducer<K,V>

实现Reducer<K,V,K,V> ,将输入直接映射到输出

LongSumReducer<K>

实现<K,LongWritable,K,LongWritable>, 计算与给定键相对应的所有值的和

<4>Partitioner:重定向 Mapper 输出

其实在mapperreducer 之间有一个非常重要的环节,就是将 mapper 的结果输出给不同的 reducer ,这就是 Partitioner 的工作:(此工作常被称为: 洗牌

一般reducer 是多个,那么 mapper 应该将键值的输出给谁呢? Hadoop 默认的机制是对键进行散列来确定 reducerHadoop 通过 HashPartitioner 类强制执行此策略。但是有的时候 HashPartitioner 会使得程序出错,即他的分发策略不符合实际的要求,那么此时就需要我们定制自己的 Partitioner( 例如针对自定义的数据类型 Edge)

public   class  EdgePartitioner  implements  Partitioner<Edge,Writable>

{

@override

public   int  getPartition(Edge key,Writable value, int  numPartitions)

{

return  key.getDepartureNode().hashCode() % numPartitions;

}

@override

public   void  configure(JobConf conf)

{

}

}

自己定制的Partitioner 只需要实现 getPartition 方法和 configure 方法即可。前者将 Hadoop对作业的配置应用在 Partitioner上,而后者返回一个介于 0reducer 任务数之间的整数,指向键值对要发送到的 reducer

Partitioner的形象的表达:(如下图)

<5>Combiner :本地 reduce

在分发mapper 之前先做一下“本地 reduce ”,也被成为合并,后面详细讲述。

<6>预定义 MapperReducer

使用预定义MapperReducer 改写前面的统计单词数量的程序: WordCount2.java

public   class  WordCount2 {

public   static   void  main(String args[])

{

JobClient client =  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 );

conf.setMapperClass(TokenCountMapper. class ); //hadoop自己的TokenCountMapper

conf.setCombinerClass(LongSumReducer. class ); //hadoop自己的LongSumReducer

conf.setReducerClass(LongSumReducer. class );

client.setConf(conf);

try

{

JobClient.runJob(conf);

} catch (Exception e)

{

e.printStackTrace();

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值