88

在 Hadoop v1 中,我为每个 7 个映射器和减速器分配了 1GB 的插槽,我的映射器和减速器运行良好。我的机器有8G内存,8个处理器。现在使用 YARN,当在同一台机器上运行相同的应用程序时,出现容器错误。默认情况下,我有以下设置:

  <property>
    <name>yarn.scheduler.minimum-allocation-mb</name>
    <value>1024</value>
  </property>
  <property>
    <name>yarn.scheduler.maximum-allocation-mb</name>
    <value>8192</value>
  </property>
  <property>
    <name>yarn.nodemanager.resource.memory-mb</name>
    <value>8192</value>
  </property>

它给了我错误:

Container [pid=28920,containerID=container_1389136889967_0001_01_000121] is running beyond virtual memory limits. Current usage: 1.2 GB of 1 GB physical memory used; 2.2 GB of 2.1 GB virtual memory used. Killing container.

然后我尝试在 mapred-site.xml 中设置内存限制:

  <property>
    <name>mapreduce.map.memory.mb</name>
    <value>4096</value>
  </property>
  <property>
    <name>mapreduce.reduce.memory.mb</name>
    <value>4096</value>
  </property>

但仍然出现错误:

Container [pid=26783,containerID=container_1389136889967_0009_01_000002] is running beyond physical memory limits. Current usage: 4.2 GB of 4 GB physical memory used; 5.2 GB of 8.4 GB virtual memory used. Killing container.

我很困惑为什么地图任务需要这么多内存。据我了解,1GB 的内存足以完成我的 map/reduce 任务。为什么当我为容器分配更多内存时,任务使用更多?是因为每个任务都有更多的拆分吗?我觉得稍微减小容器的大小并创建更多的容器会更有效,这样更多的任务可以并行运行。问题是我怎样才能确保每个容器不会被分配比它可以处理的更多的拆分?

4

9 回答 9

104

您还应该正确配置 MapReduce 的最大内存分配。从这个 HortonWorks 教程

[...]

我们集群中的每台机器都有 48 GB 的 RAM。其中一些 RAM 应该 > 保留供操作系统使用。在每个节点上,我们将为 >YARN 分配 40 GB RAM 以供操作系统使用并保留 8 GB

对于我们的示例集群,容器的最小 RAM (yarn.scheduler.minimum-allocation-mb) = 2 GB。因此,我们将为 Map 任务容器分配 4 GB,为 Reduce 任务容器分配 8 GB。

在 mapred-site.xml 中:

mapreduce.map.memory.mb: 4096

mapreduce.reduce.memory.mb: 8192

每个 Container 将为 Map 和 Reduce 任务运行 JVM。JVM 堆大小应设置为低于上面定义的 Map 和 Reduce 内存,以便它们在 YARN 分配的 Container 内存的范围内。

在 mapred-site.xml 中:

mapreduce.map.java.opts-Xmx3072m

mapreduce.reduce.java.opts-Xmx6144m

以上设置配置了 Map 和 Reduce 任务将使用的物理 RAM 的上限

把它们加起来:

  1. 在 YARN 中,您应该使用mapreduce配置,而不是mapred那些。编辑:此评论不再适用,因为您已经编辑了您的问题。
  2. 您正在配置的实际上是您想要请求的数量,而不是要分配的最大值。
  3. 最大限制使用java.opts上面列出的设置进行配置。

最后,您可能想要检查描述类似问题(和解决方案)的其他SO 问题。

于 2014-01-08T22:51:32.837 回答
49

在 Yarn 级别检查了虚拟和物理内存使用率。问题不仅在于虚拟机没有足够的物理内存。但这是因为虚拟内存使用量超出了给定物理内存的预期。

注意:这发生在 Centos/RHEL 6 上,因为它积极分配虚拟内存。

它可以通过以下方式解决:

  1. 通过将yarn.nodemanager.vmem-check-enabled设置为false来禁用虚拟内存使用检查 ;

  2. 通过将yarn.nodemanager.vmem-pmem-ratio设置为更高的值来增加 VM:PM 比率。

参考资料

https://issues.apache.org/jira/browse/HADOOP-11364

http://blog.cloudera.com/blog/2014/04/apache-hadoop-yarn-avoiding-6-time-sumption-gotchas/

在 yarn-site.xml 中添加以下属性

 <property>
   <name>yarn.nodemanager.vmem-check-enabled</name>
    <value>false</value>
    <description>Whether virtual memory limits will be enforced for containers</description>
  </property>
 <property>
   <name>yarn.nodemanager.vmem-pmem-ratio</name>
    <value>4</value>
    <description>Ratio between virtual memory to physical memory when setting memory limits for containers</description>
  </property>
于 2015-07-16T09:23:44.797 回答
15

我在 EMR 中使用 HIVE 时遇到了一个非常相似的问题。现有的解决方案都不适合我——也就是说,没有一个 mapreduce 配置适合我;也没有设置yarn.nodemanager.vmem-check-enabled为假。

但是,最终起作用的是设置tez.am.resource.memory.mb,例如:

hive -hiveconf tez.am.resource.memory.mb=4096

另一个需要考虑调整的设置是yarn.app.mapreduce.am.resource.mb

于 2016-11-09T23:41:13.773 回答
8

由于声誉低,我无法对接受的答案发表评论。但是,我想补充一点,这种行为是设计使然。NodeManager 正在杀死你的容器。听起来您正在尝试使用作为 map-reduce 任务的子进程运行的 hadoop 流。NodeManager 监控任务的整个进程树,如果它消耗的内存超过了分别在 mapreduce.map.memory.mb 或 mapreduce.reduce.memory.mb 中设置的最大值,我们希望 Nodemanager 终止该任务,否则您的任务是窃取属于您不想要的其他容器的内存。

于 2014-08-15T03:51:42.237 回答
1

在带有 Ubunto OS 的 Windows Linux 子系统上运行 yarn,错误“运行超出虚拟内存限制,正在杀死容器”我通过禁用文件 yarn-site.xml 中的虚拟内存检查来解决它

<property> <name>yarn.nodemanager.vmem-check-enabled</name> <value>false</value> </property> 
于 2020-03-09T19:58:26.267 回答
1

我正在练习 Hadoop 程序(版本 hadoop3)。通过虚拟机,我安装了 Linux 操作系统。我们在安装 Linux 时分配的内存非常有限。通过设置以下内存限制属性mapred-site.xml并重新启动 HDFS 和 YARN,我的程序就可以工作了。

 <property>
    <name>mapreduce.map.memory.mb</name>
    <value>4096</value>
  </property>
  <property>
    <name>mapreduce.reduce.memory.mb</name>
    <value>4096</value>
  </property>
于 2021-04-24T16:15:44.490 回答
1

在 EMR 中使用 spark 时,我遇到了同样的问题,设置maximizeResourceAllocation=true成功了;希望它可以帮助某人。您必须在创建集群时设置它。来自EMR 文档:

aws emr create-cluster --release-label emr-5.4.0 --applications Name=Spark \
--instance-type m3.xlarge --instance-count 2 --service-role EMR_DefaultRole --ec2-attributes InstanceProfile=EMR_EC2_DefaultRole --configurations https://s3.amazonaws.com/mybucket/myfolder/myConfig.json

myConfig.json 应该在哪里说:

[
  {
    "Classification": "spark",
    "Properties": {
      "maximizeResourceAllocation": "true"
    }
  }
]
于 2017-04-19T21:21:47.223 回答
1

我们最近也遇到了这个问题。如果问题与映射器内存有关,我想建议需要检查的几件事是。

  • 检查组合器是否启用?如果是,则意味着必须对所有记录(映射器的输出)运行归约逻辑。这发生在内存中。根据您的应用程序,您需要检查启用组合器是否有帮助。在网络传输字节和时间/内存/CPU 之间进行权衡,以减少“X”个记录的逻辑。
    • 如果您觉得组合器没有多大价值,只需禁用它即可。
    • 如果您需要组合器并且“X”是一个巨大的数字(例如数百万条记录),那么考虑更改您的拆分逻辑(对于默认输入格式使用较小的块大小,通常 1 个块大小 = 1 个拆分)以将较少数量的记录映射到单个映射器。
  • 在单个映射器中处理的记录数。请记住,所有这些记录都需要在内存中排序(mapper 的输出是排序的)。如果需要,考虑将mapreduce.task.io.sort.mb (默认为 200MB)设置为更高的值。mapred-configs.xml
  • 如果上述任何方法都没有帮助,请尝试将映射器逻辑作为独立应用程序运行,并使用 Profiler(如 JProfiler)对应用程序进行分析,并查看内存被使用的位置。这可以给你很好的见解。
于 2018-06-13T19:47:02.003 回答
0

我没有亲自检查过,但是hadoop-yarn-container-virtual-memory-understanding-and-solving-container-is-running-beyond-virtual-memory-limits-errors听起来很合理

我通过更改yarn.nodemanager.vmem-pmem-ratio为更高的值解决了这个问题,我同意:

另一个不太推荐的解决方案是通过将 yarn.nodemanager.vmem-check-enabled 设置为 false 来禁用虚拟内存检查。

于 2020-08-31T11:01:31.330 回答