我在确定配置我的Hadoop集群(CDH4)的最佳方式时遇到了麻烦,运行MapReduce1。我的情况是,我需要运行两个映射器,这些映射器需要如此大量的 Java 堆空间,以至于我不可能每个节点运行超过 1 个映射器 - 但同时我希望能够运行可以从每个节点的许多映射器中受益的作业。
我正在通过Cloudera管理UI配置集群,最大地图任务和mapred.map.child.java.opts似乎是非常静态的设置。
我想要的是一个像 X GB 可用的堆空间池这样的东西,它可以容纳这两种作业,而不必每次都重新配置 MapReduce 服务。如果我运行 1 个映射器,它应该分配 X GB 堆 - 如果我运行 8 个映射器,它应该分配 X/8 GB 堆。
我已经考虑了最大虚拟内存和 Cgroup 内存软/硬限制,但两者都不能完全满足我的需求。最大虚拟内存无效,因为它仍然是每个任务的设置。Cgroup 设置是有问题的,因为如果有更多的堆,它似乎实际上并没有将单个任务限制为更少的堆,而是允许任务使用过多的内存,然后在它这样做时终止进程。
是否可以配置我想要实现的行为?
(PS 您应该在 Hadoop 2/CDH4: mapreduce.map.java.opts
中使用此属性的较新名称。但两者都应该得到认可。
您在集群中配置的值只是默认值。可以基于每个作业覆盖它。您应该保留 CDH 中的默认值,或将其配置为普通映射器合理的值。
仅对于高内存作业,在客户端代码中,在提交Job
之前,在Configuration
对象中设置mapreduce.map.java.opts
。
如果您运行的是 MR2/YARN,答案会变得更加复杂,因为它不再按"插槽"调度,而是按容器内存调度。因此,记忆以一种新的、不同的方式进入画面,具有新的、不同的属性。(这让我感到困惑,我甚至在Cloudera。
在某种程度上它会更好,因为您用内存来表达您的资源需求,这在这里很好。您也可以将mapreduce.map.memory.mb
设置为比 JVM 堆大小大 30% 左右的大小,因为这是整个过程允许的内存。对于高内存作业,您将以相同的方式将其设置得更高。然后,Hadoop可以决定运行多少映射器,并决定将工作线程放置在哪里,并根据您的配置尽可能多地使用集群。不要对你自己想象的资源池大惊小怪。
在 MR1 中,这很难正确。从概念上讲,您希望通过 mapreduce.tasktracker.map.tasks.maximum
将每个工作线程的最大映射器数设置为 1,以及堆设置,但仅适用于高内存作业。我不知道客户是否可以在每个作业的基础上请求或设置它。我对此表示怀疑,因为它不太有意义。你不能通过控制映射器的数量来真正解决这个问题,因为你必须四处走动才能找出,更不用说控制它将运行的映射器数量了。
我认为操作系统级别的设置无济于事。在某种程度上,这些更类似于MR2/YARN对资源调度的看法。最好的选择可能是(移动到MR2并)使用MR2的资源控制,让它解决其余的问题。