如何在hadoop作业中优化洗牌/排序阶段

如何在hadoop作业中优化洗牌/排序阶段,hadoop,mapreduce,hadoop2,Hadoop,Mapreduce,Hadoop2,我正在使用单节点hadoop作业做一些数据准备。我工作中的映射器/组合器输出许多键(超过5M或6M),显然工作进展缓慢,甚至失败。映射阶段最多运行120个映射器,只有一个缩减器(这些是自动确定的,我没有为它们设置任何值)。我想优化作业,以便更有效地进行洗牌/排序阶段。我将mapreduce.task.io.sort.mb增加到300m,但作业失败,因为它的值大于映射器堆。然后我将mapred.child.java.opts设置为-Xmx1024m,但再次失败,因为它无法初始化输出收集器。这些场景

我正在使用单节点hadoop作业做一些数据准备。我工作中的映射器/组合器输出许多键(超过5M或6M),显然工作进展缓慢,甚至失败。映射阶段最多运行120个映射器,只有一个缩减器(这些是自动确定的,我没有为它们设置任何值)。我想优化作业,以便更有效地进行洗牌/排序阶段。我将
mapreduce.task.io.sort.mb增加到300m,但作业失败,因为它的值大于映射器堆。然后我将
mapred.child.java.opts
设置为-Xmx1024m,但再次失败,因为它无法初始化输出收集器。这些场景的最佳实践是什么?

默认情况下,mapreduce只选择一个减速器,这将是大多数场景的问题

您可以通过将减速器的数量设置为更高的值来更改代码
job.setNumReduceTasks(24)

或者运行hadoopjar-Dmapreduce.job.reduces=24


您需要了解您的数据,以准确确定减少的数量。Mapreduce framework根据拆分大小选择映射器的数量,但reduces应由开发人员或操作团队明确设置。

首先,由于您使用的是单节点群集,因此无法进行太多优化。在单个节点群集上,容器/插槽的数量有限,并且对于正在处理的数据量(500万到600万个密钥),作业运行速度总是很慢,也可能会失败

我将为一个完全分布式的Hadoop设置回答这个问题。在《Hadoop权威指南》一书中有一个章节(“Shuffle和Sort”),您应该阅读该章节来调整Shuffle和Sort阶段。我的回答主要受本节内容的影响,也受我自己调优MapReduce作业的经验的影响

您可以执行以下操作以实现洗牌和排序效率:

  • 合并器:使用合并器将减少传输到每个合并器的数据量,因为合并器合并映射器端的输出
  • 减速器数量:选择最佳减速器数量。如果数据量很大,那么一个减缩器不是一个好主意。另外,将reducer的数量设置为一个较高的数字不是一个好主意,因为reducer的数量还决定映射器端的分区数量。请看此处的链接:
  • 何时启动减速器:;您可以控制何时启动reduce任务。这由纱线中的配置
    mapreduce.job.reduce.slowstart.completedmaps
    确定。在完成一定百分比的映射程序之前,它不会启动减速器。默认情况下,它设置为“0.05”(这意味着5%的映射器完成后还原器启动)。如果减速器提前启动,则大多数减速器处于空闲状态,直到所有映射器完成。此外,减速器可能会占用插槽,否则映射器可能会使用这些插槽进行处理。通过控制这一点,您可以以最佳方式使用映射器/还原器插槽,并改善洗牌过程中花费的时间
  • 压缩映射器输出:建议压缩映射器输出(由配置决定:
    mapreduce.map.Output.Compress
    ),以便将较少的数据写入磁盘并传输到还原器
  • 调整配置“mapreduce.task.io.sort.mb”:增加映射程序在排序过程中使用的缓冲区大小。这将减少磁盘溢出的数量
  • 调整配置“mapreduce.reduce.input.buffer.percent”:如果reduce任务的内存需求较少,则可以将此值设置为较高的百分比。这意味着,在reduce阶段(洗牌阶段之后)使用更多的堆来保留map输出,从而减少溢出到磁盘的数量
  • 调整配置“mapreduce.reduce.shuffle.parallelcopies”:用于将映射输出复制到Reducer的线程数。请查看此处的链接:
以下是可以调整的其他配置参数,以提高洗牌和排序阶段的性能(请参见此处对这些配置的描述:):

  • mapreduce.map.sort.spill.percent
    :确定映射程序使用的内存缓冲区的阈值。当达到此阈值时,缓冲区的内容将溢出到磁盘。所以这个值决定了磁盘溢出的数量
  • mapreduce.task.io.sort.factor
    :排序期间一次合并的流的最小数量。因此,在reducer端,如果有50个映射器输出,并且该值设置为10,那么将有5轮合并(平均每轮合并10个文件)
  • mapreduce.shuffle.max.threads
    :用于将映射输出复制到还原器的工作线程数
  • mapreduce.reduce.shuffle.input.buffer.percent
    :在reducer的洗牌阶段,应使用多少堆来存储映射输出。此设置确定映射器输出在溢出到磁盘之前可以保存在内存中的量
  • mapreduce.reduce.shuffle.merge.percent
    :启动合并和溢出到磁盘过程的阈值
  • mapreduce.reduce.merge.inmem.threshold
    :启动合并进程所需的映射输出数。当达到
    mapreduce.reduce.shuffle.merge.percent
    mapreduce.reduce.merge.inmem.threshold
    时,映射输出被合并并溢出到磁盘

没错。但我主要关心的是洗牌/排序阶段。它与还原阶段没有任何关系。洗牌/排序与还原程序的数量有关。作为最终中间文件编号的洗牌和排序的一部分