0

我有一种直觉,即在运行作业时以交互方式增加/减少节点数量可以加快映射繁重的作业,但无助于减少繁重的作业,其中大部分工作都是由 reduce 完成的。

有一个关于这个的常见问题解答,但它并没有很好地解释

http://aws.amazon.com/elasticmapreduce/faqs/#cluster-18

4

1 回答 1

2

克里斯托弗史密斯回答了这个问题,他允许我在这里发帖。


一如既往......“这取决于”。您几乎总是可以依靠的一件事:稍后添加节点对您的帮助不如从一开始就拥有节点。

当您创建 Hadoop 作业时,它会被拆分为多个任务。这些任务实际上是“工作的原子”。Hadoop 允许您在创建作业期间调整 # of mapper 和 # of reducer 任务,但是一旦创建作业,它就是静态的。任务被分配到“槽”。传统上,每个节点都配置为具有一定数量的 map 任务槽和一定数量的 reduce 任务槽,但您可以对其进行调整。一些较新版本的 Hadoop 不要求您将插槽指定为用于 map 或 reduce 任务。无论如何,JobTracker 会定期将任务分配给插槽。因为这是动态完成的,所以上线的新节点可以通过提供更多插槽来执行任务来加速作业的处理。

这为了解添加新节点的现实奠定了基础。显然有一个 Amdahl 定律问题,即拥有比挂起任务更多的插槽几乎没有完成(如果您启用了推测执行,它确实有所帮助,因为 Hadoop 将安排相同的任务在许多不同的节点上运行,因此可以将慢速节点的任务如果有空闲资源,则由更快的节点完成)。因此,如果您没有使用许多 map 或 reduce 任务来定义您的工作,那么添加更多节点不会有太大帮助。当然,每项任务都会带来一些开销,所以你也不想发疯。这就是为什么我建议任务大小的指导方针应该是“需要大约 2-5 分钟才能执行的事情”。

当然,当您动态添加节点时,它们还有另一个缺点:它们没有任何本地数据。显然,如果您处于 EMR 管道的开头,那么所有节点中都没有数据,所以没关系,但是如果您有一个由许多作业组成的 EMR 管道,并且早期的作业将其结果保存到 HDFS,您获得巨大的性能提升,因为 JobTracker 将有利于塑造和分配任务,因此节点具有可爱的数据局部性(这是整个 MapReduce 设计的核心技巧,以最大限度地提高性能)。在 reducer 方面,数据来自其他 map 任务,因此与其他节点相比,动态添加的节点确实没有劣势。

因此,原则上,动态添加新节点实际上不太可能有助于从 HDFS 读取的 IO 绑定映射任务。

除了...

Hadoop 有各种秘籍来优化性能。一次是它在 map 任务完成/reducer 启动之前开始将 map 输出数据传输到 reducer。这显然是映射器生成大量数据的作业的关键优化。您可以在 Hadoop 开始启动传输时进行调整。无论如何,这意味着新启动的节点可能处于劣势,因为现有节点可能已经拥有如此巨大的数据优势。显然,映射器传输的输出越多,劣势就越大。

这就是一切的真正运作方式。但在实践中,许多 Hadoop 作业都有映射器以 CPU 密集型方式处理大量数据,但输出到减速器的数据相对较少(或者它们可能会向减速器发送大量数据,但减速器仍然非常简单,所以根本不受 CPU 限制)。通常作业会有很少的(有时甚至是 0 个)reducer 任务,因此即使是额外的节点也可以提供帮助,如果您已经为每个未完成的 reduce 任务提供了一个 reduce 槽,那么新节点也无济于事。出于显而易见的原因,新节点也对 CPU 密集型工作提供了不成比例的帮助,所以因为这往往映射任务多于减少任务,这是人们通常看到的胜利。如果您的映射器受 I/O 限制并从网络中提取数据,那么添加新节点显然会增加集群的总带宽,因此它会有所帮助,但如果您的映射任务受 I/O 限制并读取 HDFS,最好的办法是有更多的初始节点,数据已经分布在 HDFS 上。由于作业结构不佳,reducer 会受到 I/O 限制的情况并不少见,在这种情况下,添加更多节点会有很大帮助,因为它会再次分割带宽。

当然也有一个警告:对于一个非常小的集群,reducer 可以从本地节点上运行的映射器读取大量数据,并且添加更多节点会将更多数据转移到速度慢得多的网络上。您还可能遇到这样的情况:reducer 大部分时间只是从所有向它们发送数据的映射器中多路复用数据处理(尽管这也是可调的)。

如果您要问这样的问题,我强烈建议您使用亚马逊提供的 KarmaSphere 之类的东西来分析您的工作。它将让您更好地了解瓶颈在哪里以及提高性能的最佳策略是什么。

于 2012-10-09T16:26:23.510 回答