记一次MapReduce的内存溢出

背景:

最近使用MapReduce做离线数据清洗,在map段做简单的数据过滤,有经纬度的发送到reduce端,没经纬的过滤掉。reduce端将数据整理出来,按业务模型拼接成字符串写入HDFS。供hive作为外表进行后续数据处理分析。

问题:

该批数据总共2T大小,MapReduce执行第一次时,不出意料的崩溃了。每次都大概在map阶段执行到61%左右。

排查:

    查看日志发现果然内存溢出:java.lang.OutOfMemoryError: GC overhead limit exceeded。

Exception in thread thread_name: java.lang.OutOfMemoryError: GC Overhead limit exceededCause: The detail message “GC overhead limit exceeded” indicates that the garbage collector is running all the time and Java program is making very slow progress. After a garbage collection, if the Java process is spending more than approximately 98% of its time doing garbage collection and if it is recovering less than 2% of the heap and has been doing so far the last 5 (compile time constant) consecutive garbage collections, then a java.lang.OutOfMemoryError is thrown. This exception is typically thrown because the amount of live data barely fits into the Java heap having little free space for new allocations.Action: Increase the heap size. The java.lang.OutOfMemoryError exception for GC Overhead limit exceeded can be turned off with the command line flag -XX:-UseGCOverheadLimit.

 大概意思就是说,JVM花费了98%的时间进行垃圾回收,而只得到2%可用的内存,频繁的进行内存回收(最起码已经进行了5次连续的垃圾回收),JVM就会曝出ava.lang.OutOfMemoryError: GC overhead limit exceeded错误。本质上还是堆内存不足。

其实对于大数据执行来说内存溢出问题司空见惯。按照惯例一套标准流程,减小每个map的split字节大小,增加map数,增加每个container的堆内存,增加每个map的堆内存,能想到的参数我试了个遍。其实缕了一下代码,我认为我们的map不应该存在内存溢出的情况。因为并没有进行复杂的关联计算,并且不会存在数据倾斜问题。但是任务每次还是在60%左右卡死,同时,我观察到一个现象。每次程序崩溃的时候,yarn 的任务追踪页面都会反应的异常慢,看来我之前想的方向有问题,看来不是map容器的堆内存溢出。


异常图如上

仔细缕了一遍异常,发现是ContainerLauncherImpl 这个类的报错,意思是容器启动的时候发生的问题。

![
源码

查了下hadoop 这块的代码,果然是申请容器的时候出了问题,MRAppMaster负责向yarn的resourcemanager去申请资源启动容器。初步得出了应该是MRAppMaster的内存溢出。
ApplicationMaster向资源调度器申请执行任务的资源容器Container,运行用户自己的程序任务job(我们可以用浏览器看yarn
里的job进展),监控整个任务的执行,跟踪整个任务的状态,处理任务失败以异常情况。这也对应了我们看yarn上的任务监控会崩溃的情况。

解决:

通过调整参数,yarn.app.mapreduce.am.command-opts、yarn.app.mapreduce.am.resource.mb加大了MRAppMaster的内存。同时分析待处理的源数据。发现每个文件10MB大小,总共有18万,MapReduce处理文件,默认使用FileInputFormat,但是这个处理小文件是,会每一个小文件生成一个map,所以以为着原来我们的任务有18万个map,这应该突破了原来的MRAppMaster所能维护的map的极限,频繁的申请创建、销毁container也消耗了大量的计算资源,导致了内存溢出、任务崩溃。hadoop处理大量小文件建议使用CombineFileInputFormat来合并输入数据,减少map数量。修改完之后,map数量锐减到2800多个,程序不再报内存溢出,同时提升了执行速度。

至此,问题得到了解决。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值