我需要一些帮助来理解mapreduce流,不是理论上的,而是参考普通java代码片段。我一直在阅读关于hadoop处理的教程、api、论坛和其他主题相关的内容;MapReduce。我非常熟悉hadoop的流程和处理方法。我理解的问题与java中的mapreduce编码有关。我已经阅读并尝试了一些已经存在的代码;i、 我不能理解的是原始数据流入mapper和reducer类(严格地说是java代码,而不是理论流)。
我也会试着用代码来表达它;也许我可以这样让自己更容易理解。比如说经典的wordcount程序;我在某处找到的map&reduce类声明如下:
public static class Map extends MapReduceBase implements
Mapper<LongWritable, Text, Text, IntWritable>
public static class Reduce extends MapReduceBase implements
Reducer<Text, IntWritable, Text, IntWritable>
我对上述代码段的查询:
我该如何决定这4个参数的类型?
API的定义是
org.apache.hadoop.mapreduce.mapper(keyin,valuein,keyout,valueout)
如果我通过命令行将文件传递给我的程序,那么整个内容将以什么参数传递?根据对hadoop流的理解,我将使用前两个参数,即keyin和valuein。键将是单词,而值将在那里计数(无论Map阶段的输出是什么)。
如何声明我的密钥是否应该是可长写的。如果我只声明integer类型的第一个参数呢(我说的不是integer和longwritable类型之间的区别,而是基本决定)。
我如何决定我的问题的哪一部分应该在我的mapper类中,哪一部分应该在reducer类中?
mapper&reducer类中声明的参数类型应该相同还是不同?就像上面的声明一样,它们是不同的。这算什么?我能猜到的唯一答案是map阶段输出的中间值可能与map类的输入类型不同(不确定,所以请原谅这个解释(如果荒谬的话)。
例如,我尝试编写一个小代码,用逗号分隔的整数值找出一个小文本文件中的最大数。首先,我不能决定在哪里进行处理;在mapper类还是reducer类中?通过查看大量代码,我得出了一个结论,即处理应该在reducer类中进行,同时我可以在mapper类中对输入应用一些基本检查。这个逻辑我自己假设的,所以你可以在这上面玩得开心:)有人能告诉我这段代码有什么问题吗&也许能帮我弄清楚我的理解吗?
我的代码:
public class mapTest {
public static class Map extends MapReduceBase implements
Mapper<Text, Text, Text, Reporter>{
@Override
public void map(Text text, Text value,
OutputCollector<Text, Reporter> output, Reporter arg0)
throws IOException {
// TODO Auto-generated method stub
String val = value.toString();
if(val.equals(null)){
System.out.println("NULL value found");
}
output.collect(value, arg0);
}
}
public static class Reduce extends MapReduceBase implements
Reducer<Text, Text, Text, Reporter>{
public void reduce(Text key, Iterator<Text> value,OutputCollector<Text, Reporter> output, Reporter arg0)
throws IOException {
// TODO Auto-generated method stub
Text max = value.next();
while(value.hasNext()){
Text current = value.next();
if(current.compareTo(max) > 0)
max = current;
}
output.collect(key, (Reporter) max);
}
}
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
JobConf conf = new JobConf();
conf.setMapperClass(Map.class);
conf.setReducerClass(Reduce.class);
conf.setOutputKeyClass(Text.class);
conf.setOutputValueClass(Text.class);
conf.setInputFormat(TextInputFormat.class);
conf.setOutputFormat(TextOutputFormat.class);
FileInputFormat.setInputPaths(conf, new Path(args[0]));
FileOutputFormat.setOutputPath(conf, new Path(args[1]));
JobClient.runJob(conf);
}
}
附言:论点类型,我只是随便提到,虽然除了记者类型,我不明白其他类型的重要性。
在发布这个问题之前,我做了所有我能做的研究。请帮我理解这个流程。我不想把所有的事情都搞砸了,我只是从别的地方拿起密码,做化妆品。
提前谢谢-
阿迪尔
1条答案
按热度按时间lp0sw83n1#
mapper的keyin、valuein和reducer的keyout、valueout分别取决于您的输入/输出格式。map输出k/v对必须与减速器的输入匹配。
对于文本文件,您可能需要textinputformat。键是文件的字节偏移量,值是行。从那里你可以像解析普通字符串一样解析出你想要的任何数据。
longwritable vs intwritable就像选择int vs long一样。这完全取决于你的数据。
大部分工作是应该在mapper还是reducer中完成,这有待商榷。通常使用的Map器比还原器多,因此可以利用更多的并行性。您还可以减少在减少数据量之前需要洗牌和排序的数据量。但是,reducer的所有值都是基于键配置的,因此处理在那里也是有意义的。就我个人而言,我尽可能早地尽量减少数据量。当所有的东西都能放在内存中时,mapreduce是最有效的。