一、概念综述
MapReduce是一种可用于数据处理的编程模型(或计算模型),该模型可以比较简单,但想写出有用的程序却不太容易。MapReduce能将大型数据处理任务分解成很多单个的、可以在服务器集群中并行执行的任务,而这些任务的计算结果可以合并在一起计算最终的结果。最重要的是,MapReduce的优势在于易于编程且能在大型集群(上千节点)并行处理大规模数据集,以可靠,容错的方式部署在商用机器上。
从MapReduce的所有长处来看,它基本上是一个批处理系统,并不适合交互式分析。不可能执行一条查询并在几秒内或更短的时间内得到结果。典型情况下,执行查询需要几分钟或更多时间。因此,MapReduce更适合那种没有用户在现场等待查询结果的离线使用场景。
在MapReduce整个过程可以概括为以下过程:
input split --> map --> shuffle --> reduce --> output
下图是《Hadoop权威指南》给出的MapReduce运行过程:
MapReduce运行过程图
MapReduce作业是客户端需要执行的一个工作单元:它包括输入数据、MapReduce程序和配置信息。Hadoop将作业分成若干个任务(task)来执行,其中包括两类任务:map任务和reduce任务。这些任务运行在集群的节点上,并通过YARN进行调度。如果一个任务失败,它将在另一个不同的节点上自动重新调度运行。
Input Split:
Hadoop将MapReduce的输入数据划分成等长的小数据块,称为输入分片(input split)或简称“分片”。Hadoop为每一个分片构建一个map任务,并由该任务来运行用户自定义的map函数从而处理分片中的每条记录。
拥有许多分片,意味着处理每个分片所需要的时间少于处理整个输入数据所花的时间。因此,如果我们并行处理每个分片,且每个分片数据比较小,那么整个处理过程将获得更好的负载平衡,因为一台较快的计算机能够处理的数据分片比一台较慢的计算机更多,且成一定的比例。即使使用相同的机器,失败的进程或其他并发运行的作业能够实现满意的负载平衡,并且随着分片被切分得更细,负载平衡的质量会更高。另一方面,如果分片切分得太小,那么管理分片得总时间和构建map任务得总时间将决定作业的整个执行时间。对于大多数作业来说,一个合理的分片大小趋向于HDFS的一个块的大小,这样可以确保存储在单个节点上的最大输入块的大小。数据块默认是128MB,不过可以针对集群调整这个默认值,或在每个文件创建时指定。
Map:
map任务会将集合中的元素从一种形式转化成另一种形式,在这种情况下,输入的键值对会被转换成零到多个键值对输出。其中输入和输出的键必须完全不同,输入和输出的值则可能完全不同。
Hadoop在存储有输入数据(HDFS中的数据)的节点上运行map任务,可以获得最佳性能,因为它无需使用宝贵的集群带宽资源。这就是所谓的“数据本地化优化”。但是,有时对于一个map任务的输入分片来说,存储该分片的HDFS数据块复本的所有节点可能正在运行其他map任务,此时作业调度需要从某一数据块所在的机架中的一个节点上寻找一个空闲的map槽(slot)来运行该map任务分片。仅仅在非常偶然的情况下(该情况基本上不会发生),会使用其他机架中的节点运行该map任务,这将导致机架与机架之间的网络传输。下图显示了这三种可能性。
map任务的网络传输的三种可能性图
map任务的输出被称为中间键和中间值,会被发送到reducer做后续处理。但输出结果只写入本地硬盘,而非HDFS。这是为什么?因为map的输出是中间结果:该中间结果由reduce任务处理后才产生最终输出结果,而且一旦作业完成,map的输出结果就可以删除。因此,如果把它存储在HDFS中并实现备份,难免有些小题大做。如果运行map任务的节点在将map中间结果传送给reduce任务之前失败,Hadoop将在另一个节点上重新运行这个map任务以再次构建map中间结果。
Shuffle和排序:
shuffle和排序在MapReduce流程图中的执行过程
MapReduce确保每个reducer的输入都是按键排序的。系统执行排序、将map输出作为输入传给reduce的过程称为