2011-11-05 131 views
9

我试图在Hadoop集群上运行一个高内存作业(0.20.203)。我修改了mapred-site.xml来强制执行一些内存限制。用hadoop指定内存限制

<property> 
    <name>mapred.cluster.max.map.memory.mb</name> 
    <value>4096</value> 
    </property> 
    <property> 
    <name>mapred.cluster.max.reduce.memory.mb</name> 
    <value>4096</value> 
    </property> 
    <property> 
    <name>mapred.cluster.map.memory.mb</name> 
    <value>2048</value> 
    </property> 
    <property> 
    <name>mapred.cluster.reduce.memory.mb</name> 
    <value>2048</value> 
    </property> 

在我的工作中,我指定了需要多少内存。不幸的是,即使我正在使用-Xmx2g运行我的进程(作为控制台应用程序,作业将运行得很好),我需要为映射程序请求更多的内存(作为子问题,为什么是这样?)或者它杀害。

val conf = new Configuration() 
conf.set("mapred.child.java.opts", "-Xms256m -Xmx2g -XX:+UseSerialGC"); 
conf.set("mapred.job.map.memory.mb", "4096"); 
conf.set("mapred.job.reduce.memory.mb", "1024"); 

因为我正在执行身份缩减器,所以减速器几乎不需要任何内存。

class IdentityReducer[K, V] extends Reducer[K, V, K, V] { 
    override def reduce(key: K, 
     values: java.lang.Iterable[V], 
     context:Reducer[K,V,K,V]#Context) { 
     for (v <- values) { 
     context write (key, v) 
     } 
    } 
    } 

但是,减速机仍在使用大量的内存。是否有可能给reducer不同的映射器JVM参数? Hadoop杀死了reducer并声称它使用了3960 MB的内存!减员最终失败了。这怎么可能?

TaskTree [pid=10282,tipID=attempt_201111041418_0005_r_000000_0] is running beyond memory-limits. 
Current usage : 4152717312bytes. 
Limit : 1073741824bytes. 
Killing task. 

UPDATE:即使我指定与cat作为mapper和uniq作还原剂和-Xms512M -Xmx1g -XX:+UseSerialGC我的任务接管虚拟内存2g侧流工作!这看起来很奢侈,最大堆大小是4倍。

TaskTree [pid=3101,tipID=attempt_201111041418_0112_m_000000_0] is running beyond memory-limits. 
Current usage : 2186784768bytes. 
Limit : 2147483648bytes. 
Killing task. 

更新说明:original JIRA改变内存使用的配置格式特别提到的是Java的用户在物理内存中最感兴趣的,以防止抖动。我认为这正是我想要的:如果可用的物理内存不足,我不希望节点启动映射器。但是,这些选项似乎都是作为虚拟内存限制实施的,这些限制很难管理。

+0

只是好奇 - 设置最大内存使用mapred.child.java.opts/-Xmx和mapred.job.map.memory.mb/mapred.job.reduce.memory.mb之间的区别是什么?我在SO(http://goo.gl/aIBLr)中提出了一个查询,但没有回应。 –

回答

6

检查你的ulimit。从Cloudera,在0.20.2版本,但类似的问题可能适用于更高版本:

...如果你设置mapred.child.ulimit,重要的是它必须是堆更加 两倍是很重要的尺寸值设置在mapred.child.java.opts中。例如,对于 示例,如果您设置了1G堆,请将mapred.child.ulimit设置为2.5GB。子进程现在保证至少分叉一次,而分叉 暂时需要两倍的虚拟内存开销。

以编程方式设置mapred.child.java.opts是“太迟了”;你可能想验证它是否真正生效,如果没有,就把它放到你的mapred-site.xml中。

+1

似乎'ulimit'是比'mapred.job.reduce.memory.mb'更严格的约束,并且在我的安装中未设置。这是一个有用的参考多少虚拟机允许然而... – schmmd