《Hadoop实战》第三章之MapReduce计算模型
1.为什么要用MapReduce
MapReduce的流行是有理由的。它非常简单、易于实现且扩展性强。大家可以通过它轻易地编写出同时在多台主机上运行的程序,也可以使用Ruby、Python、 PHP和C++等非Java类语言编写Map或Reduce程序,还可以在任何安装Hadoop的集群中运行同样的程序,不论这个集群有多少台主机。MapReduce适合处理海量数据,因为它会被多台主机同时处理,这样通常会有较快的速度。
2 MapReduce计算模型
要了解MapReduce,首先需要了解MapReduce的载体是什么。 在Hadoop中,用于执行MapReduce任务的机器有两个角色:一个是JobTracker,另一个是TaskTracker。JobTracker 是用于管理和调度工作的,TaskTracker 是用于执行工作的。一个Hadoop集群中只有一台JobTracker。
2.1 MapReduce Job
在Hadoop中,每个MapReduce任务都被初始化为一个Job。每个Job又可以分为两个阶段: Map阶段和Reduce阶段。这两个阶段分别用两个函数来表示,即Map函数和Reduce函数。 Map函数接收-一个<key, value>形式的输人,然后产生同样为<key, value>形式的中间输出, Hadoop会负责将所有具有相同中间key值的value集合到一起传递给Reduce函数,Reduce函数接收- 个如<key, (list of values)> 形式的输入, 然后对这个value集合进行处理并输出结果,Reduce 的输出也是<key, value>形式的。
2.2 几个方法的解释
(1)InputFormat()和InputSplit
InputSplit是Hadoop中用来把输人数据传送给每个单独的Map,InputSplit存储的并非数据本身,而是一个分片长度和一个记录数据位置的数组。生成InputSplit的方法可以通过Inputformat()来设置。当数据传送给Map时,Map会将输入分片传送到InputFormat()上,InputFormat() 则调用getRecordReader()方法生成RecordReader, RecordReader 再通过creatKey()、creatValue() 方法创建可供Map处理的<key, value>对,即<k1,v1>。简而言之,InputFormat()方法是用来生成可供Map()处理的<key,value>对的。
(2)OutputFormat()
对于每一种输入格式都有一种输出格式与其对应。同样,默认的输出格式是TextOutputFormat,这种输出方式与输入类似, 会将每条记录以一行的形式存人文本文件。不过,它的键和值可以是任意形式的, 因为程序内部会调用toStringO方法将键和值转换为String类型再输出。
(3) Map()和Reduce()
Map()方法和Reduce()方祛是本章的重点,从前面的内容知道,Map()函数接收经过InputFormat处理所产生的<k1, v1>,然后输出<k2, v2>。Map()函数继承自MapReduceBase,并且它实现了Mapper接口,此接口是一个范型类型, 它有4种形式的参数,分别用来指定Map()的输入key值类型、输人value值类型、输出key值类型和输出value值类型。在本例中,因为使用的是TextInputFormat,它的输出key值是LongWritable类型, 输出value值是Text类型,所以Map()的输人类型即为<LongWritable, Text>。如前面的内容所述,在本例中需要输出<word, 1>这样的形式,因此输出的key值类型是Text,输出的value值类型是IntWritable。
实现此接口类还需要实现Map()方法,Map() 方祛会负责具体对输入进行操作,在本例中,Map()方法对输人的行以空格为单位进行切分,然后使用OutputCollect收集输出的<word,1>,即<k2,v2>。与Map()类似,Reduce()函数也继承自MapReduceBase,需要实现Reducer接口。Reduce()函数以Map()的输出作为输人,因此Reduce()的输入类型是<Text, IneWritable>。而Reduce()的输出是单词和它的数目,因此,它的输出类型是<Text, IntWritable>。Reduce()函数也要实现Reduce()方法,在此方法中,Reduce()函数将输人的key值作为输出的key值,然后将获得的多个value值加起来,作为输出的value值。
#uc#
