MapReduce作业(job)是客户端需要执行的一个工作单元:他包括输入数据、MapReduce程序和配置信息。Hadoop将作业分成若干个任务(task)来执行,其中包括两类任务:map任务和reduce任务
。这些任务运行在集群的节点上,并通过YARN
进行调度。如果一个任务失败,他将在另一个不同的节点上自动重新调度运行。
Hadoop将MapReduce的输入数据划分成等长的小数据块,称为输入分片
(input split)或简称“分片”。Hadoop为每个分片构建一个map
任务,并由该任务来运行用户自定义的map函数从而处理分片中的每条记录。
关于分片
拥有许多分片,意味着处理每个分片所需要的时间少于处理整个输入数据所花的时间。因此,如果我们并行处理每个分片,且每个分片数据比较小,那么整个处理过程将获得更好的负载均衡。
另一方面,如果分片切分的太小,那么管理分片的总时间和构建map任务的总时间将决定作业的整个执行时间。对于大多数作业来说,一个合理的分片大小趋向于HDFS的一个块的大小,默认是128MB,不过可以针对集群调整这个默认值(对所有新建的文件),或在每个文件创建时指定。
Hadoop在存储有输入数据(HDFS中的数据)的节点上运行map任务,可以获得最佳性能,因为他无需使用宝贵的集群带宽资源。这就是所谓的“数据本地化优化”
(data locality optimization)。但是,有时对于一个map任务的输入分片来说,存储该分片的HDFS数据块复本的所有节点可能正在运行其他map任务,此时作业调度需要从某一数据块所在的机架中的一个节点上寻找一个空闲的map槽(slot)来运行该map任务分片。仅仅在非常偶然的情况下(该情况基本上不会发生),会使用其他机架中的节点运行该map任务,这将导致机架与机架之间的网络传输。
现在我们应该清楚为什么最佳分片的大小应该与块大小相同:因为他是确保可以存储在单个节点上的最大输入块的大小。
如果分片跨越两个数据块,那么对于任何一个HDFS节点,基本上都不可能同时存储这两个数据块,因此分片中的部分数据需要通过网络传输到map任务运行的节点,与使用本地数据运行整个map任务相比,这种方法显然效率更低。
map任务将其输出写入本地硬盘
,而非HDFS。这是为什么?因为map的输出是中间结果:该中间结果由reduce任务处理后才产生最终输出结果,而且一旦作业完成,map的输出结果就可以删除。因此,如果把他存储在HDFS中并实现备份,难免有些小题大做。如果运行map任务的节点在将map中间结果传送给reduce任务之前失败,Hadoop将在另一个节点上重新运行这个map任务以再次构建map中间结果。
reduce任务并不具备数据本地化的优势,单个reduce任务的输入通常来自于所有mapper的输出
。因此,排过序的map输出需要通过网络传输发送到运行reduce任务的节点。数据在reduce端合并,然后由用户定义的reduce函数处理。reduce的输出通常存储在HDFS中以实现可靠存储
。对于reduce输出的每个HDFS块,第一个复本存储在本地节点上,其他复本出于可靠性考虑存储在其他机架的节点中。因此,将reduce的输出写入HDFS确实需要占用网络带宽
,但这与正常的HDFS管线写入的消耗一样。
![](https://img.haomeiwen.com/i1527003/f5800467afb297e8.png)
网友评论