我有简单的映射器和简单的reducer(它是由一个字段连接两个大表):
protected void reduce(StringLongCompositeKey key, Iterable<Text> values, Context context)
throws IOException, InterruptedException {}
foreach(Text text : values) {
// do some operations with one record and then emit it using context.write
// so nothing is storing in memory, one text record is small (mo more then 1000 chars)
}
}
但我得到了以下错误
14/09/25 17:54:59 INFO mapreduce.Job:map 100%reduce 28%14/09/25 17:57:14 INFO mapreduce.Job:Task Id:attempt_1410255753549_9772_r_000020_0,Status:FAILED Container [pid = 24481 ,containerID = container_1410255753549_9772_01_001594]超出了物理内存限制 . 当前用法:使用4.1 GB的4 GB物理内存;使用4.8 GB的8.4 GB虚拟内存 . 杀死容器 .
有一个细微差别 - )
Iterable<Text> values
太长了!正如我之前所考虑的那样,并且仍然认为它是真的,Iterable按需加载下一个记录,并且hadoop处理它不应该是问题,而不消耗大量的RAM .
在改组或排序时是否会出现此错误?有关处理长序列的特殊信息吗?
2 回答
确实 . 在代码实际运行之前,当数据被移动到reducers时,这似乎发生在shuffle阶段 .
减少百分比的工作方式是0-33%是洗牌阶段,数据发送到减速器,33-66%是排序阶段,最后33%表示容器运行 .
看来洗牌排序内存不足 . 您可以检查配置以了解如何分配内存 . 通过使用java.opts,您可以确保reducer的java堆不会声明所有内存,因为它还需要内存用于OS和核心进程 . 根据经验,我为这些留下512MB . shuffle排序中的内存不足可能与竞争内存的shuffle排序有关 . 降低允许随机播放使用的百分比通常可以解决问题 . Ofc,最佳设置取决于您的设置 .