第二章之关于MapReduce

MapReduce 是一种可用于数据处理的编程模型。Hadoop可以运行由各种语言编写的MapReduce程序。MapReduce程序本质上是并行运行的,MapReduce的优势在于处理大规模数据集。

如果说处理大规模数据集 使用多线程的方法,也会有很多问题,最主要的是协调性和可靠性两大因素,哪个进程负责运行整个作业,我们如何处理失败的进程?

 

使用Hadoop分析数据

需要把查询表示成MapReduce作业。

Map阶段和Reduce阶段。每个阶段都以 键/值对作为输入和输出,并由程序员选择他们的类型。需要定义两个函数:map函数和Reduce函数。

 

新增的Java MapReduce API

新的多使用虚类 ,而不是接口,因为更容易扩展实现,比如新的mapper和reducer

新的API在org.apache.hadoop.mapreduce中,老的在org.apache.hadoop.mapred中

新的API充分使用上下文对象,使用户代码能够于MapReduce系统通信

新的API同时支持 push和pull方式的迭代

新的API实现了配置的统一。旧的是通过JobConf对象配置作业,新的API是通过Congiguration来完成

新的作业控制由Job类实现,而不是JobClient类

输出的文件的命名方式稍有不同

 

横向扩展

我们需要把数据存储在分布式文件系统中,一般为HDFS,由此允许Hadoop把MapReduce计算移到存储有部分数据的各个台式机器上。

 

数据流

MapReduce作业(job)是客户端需要执行的一个工作单元,包括 输入数据,MapReduce程序和配置信息。Hadoop把作业分为若干个小任务(task)来执行,其中包括两类任务:Map任务和reduce任务。

两类节点控制着作业执行过程:一个jobtracker以及一系列tasktracker。 jobtracker通过调度tasktracker上运行的任务,来协调所有运行在系统上的作业,tasktracker在运行任务的同时把运行进度报告发给jobtracker,jobtracker由此记录每项作业任务的整体进度情况。如果一个任务失败,jobtracker可以在另外一个tasktracker节点上重新调度该任务。

Hadoop把MapReduce的输入数据划分成等长的小数据块,称为输入分片(input split).Hadoop为每个分片构建一个map任务,并由该任务来运行用户自定义的Map函数从而处理分片中的每条记录。

一个合理的分片的大小趋向于HDFS的一个块的大小,默认是64M.

Hadoop在存储有输入数据(HDFS中的数据)的节点上运行Map任务,可以获得最佳性能。也就是所谓的数据本地话优化

(data locality optimization)

Map任务将其出入写入本地硬盘,而非HDFS。

原因:因为map的输出是中间结果,该中间结果由reduce任务处理后才会产生最终输出结果。而且一旦作业完成,map的输出结果可以被删除,因此如果把他存储在HDFS中并实现备份,小题大做。如果该借点在运行的map任务在把map中间结果传送给reduce任务之前失败,hadoop将在另一个节点上重新运行这个map任务以再次构建map中间结果。

Reduce任务不具备本地化的优势---单个的reduce任务的输入通常来自于所有的mapper的输出。Reduce的输出通常存在HDFS中以实现可靠存储,对于每个reduce输出的HDFS块,第一个复本存储在本地节点上,其他的复本存储在其他的机架借点中。

 

Reduce任务的数量并非由输入数据的大小决定,而是特别指定。如果有多个reduce任务,那么每个map任务都会对其输入进行分区,即为每个reduce任务建立一个分区,每个分区有很多键(以及对应的值),但是每个键对应的键/值对都在同一分区中。分区由用户定义的分区函数控制,但是通常默认的分区器通过哈希函数来分区,比较高效。

Map任务和reduce任务之间的数据称之为shuffle(混洗),因为每个reduce的任务的输入都来自许多map任务,混洗一般比下图复杂,而且混洗参数对作业执行的时间影响交大。

最后也可能没有reduce任务,当数据处理可以完全并行的时候,即无需清洗,可能会出现无reduce任务的情况。在这种情况下,唯一的非本地节点数据传输是map任务把结果直接写入HDFS.

 

Combiner

集群上可以用带宽限制mapreduce作业的数量,因此重要的一点是尽量避免map任务和reduce任务之间的数据传输。

Hadoop允许用户针对map任务的输出指定一个合并函数。

合并函数的输出作为reduce函数的输入。他是一个优化方案。所以无法确定map任务输出中任何一条记录需要调用多少次合并函数。

有时候combiner不能取代reduce函数。,但即便这样我们仍需要他,因为他能减少map和reduce之间的数据传输量。

合并函数是通过reducer接口来定义的。

 

运行分布式的MapReduce作业

无需修改,便可以在一个完整的数据集上直接运行这个程序。这个MapReduce的优势之一:它可以根据数据量的大小和硬件规模进行扩展。

Hadoop的Streaming

Hadoop提供了MapReduce的API,并允许你使用非JAVA语言来写自己的Map和reduce函数。Hadoop使用Unix标准流作为Hadoop和应用程序之间的接口,所以我们可以使用任何编程语言通过标准输入/输出来写MapReduce程序。

Streaming天生适合用于文本处理,在文本模式下使用,它有一个数据的行视图,map的输入数据通过标准输入流传递给map函数,并且是一行一行的传输,

最后把结果行写到标准输出。reduce函数的输入格式相同,通过制表符来分隔的键/值对,并通过标准输入流进行传输。reduce函数从标准输入流中读取输入行,该输入已经由Hadoop框架根据键排过序,最后把结果写入标准输出。

 

 

posted @ 2012-07-22 00:20  honkcal  阅读(703)  评论(0编辑  收藏  举报