1.案例描述:
hive有个定时任务平时正常,没有啥问题,正常一般大概执行1个小时左右,但是今天突然报错了,报错代码::running beyond physical memory limits. Current usage: 2.0 GB of 2 GB physical memory used; 3.9 GB of 4.2 GB virtual memory used. Killing container。
2.分析解决
看报错日志,显示说是内存不够,container分配的2g物理内存已经使用完了,另外虚拟内存4.2g已经使用了3.9g。所以任务被杀死。网上找了一些问题的排查,比如说调整增加了map和reduce的内存,,设置虚拟内存的比率,取消虚拟内存的检查等等,但是其实好多都没有用,要具体问题具体分析。下面具体分析一下。
1.查看大数据集群配置为每个container分配到内存的区间,从下面参数的结果可知,我们公司yarn的配置为每个container可申请的内存区间是1g-8g之间。具体每个container实际分配多少内存要看实际平台资源的负载情况 ,以及任务的优先级等因素。甚至有种方法说增加下面set yarn.scheduler.minimum-allocation-mb 参数的值,即将每个container的分配内存区间值调大。但是实际上这个值要通过yarn-site.xml文件进行配置,并且需要重启集群才会生效,而实际开发中,这种方法不太可能实现。
1.查看yarn为每个container分配的内存区间
hive>set yarn.scheduler.minimum-allocation-mb;
yarn.scheduler.minimum-allocation-mb=1024
hive>set yarn.scheduler.maximum-allocation-mb;
yarn.scheduler.maximum-allocation-mb=8192
2.从下面看到集群的配置为每个maptask和reduce task可使用的内存大下默认为2g。所以这个时候,如果是因为平台资源紧张造成部分任务因内存不够而失败(之前很多时候可以正常跑成功的任务)。这时候单方面调大mapreduce.map.memory.mb和mapreduce.reduce.memory.mb的值没有任何意义,因为尽管每个container可以分配的内存是1-8g,但现在因为集群资源紧张可能分配的内存很小,比如小于2个g,那么你在调大运行在container上到map和reduce可使用内存,没有任何意义。有一种情况调大mapreduce.map.memory.mb和mapreduce.reduce.memory.mb的值有用,那就是平台资源很丰富,每个container实际分配的内存很大,比如6个g。这样会加快程序的运行,但值太大也会造成资源的浪费。
1.查看每个map,reduce默认使用内存的配置大小
hive>set mapreduce.map.memory.mb;
mapreduce.map.memory.mb=2048
hive>set mapreduce.reduce.memory.mb;
mapreduce.reduce.memory.mb=2048
3.增加虚拟内存的虚拟化比率
通过下面可知,默认每个maptask和reudcetask虚拟化的内存比例是2.1。这里公司集群每个map,reduce设置的默认内存使用大小为2g。所以虚拟内存最大2.1*2=4.2g(上面报错4.2g的来源:3.9 GB of 4.2 GB virtual memory used.),而且这个参数也是通过yarn-site.xml进行配置。其实实际开发中可以对应的配置大些。
hive (default)> set yarn.nodemanager.vmem-pmem-ratio;
yarn.nodemanager.vmem-pmem-ratio=2.1
4. 配置yarn不内存检查
通过yarn-site.xml文件将yarn.nodemanager.vmem-check-enabled设置为false,然后重启集群。但是这种不建议,可能会造成内存泄露。
hive (default)> set yarn.nodemanager.vmem-check-enabled;
yarn.nodemanager.vmem-check-enabled=true
5.增加map和reduce的个数
很显然,此举是将每个map和reduce的工作量降小了,可以起到一定作用。一般maptask的个数由文件大小,切片信息等确定,而reduce的个数由最终需要聚合的结果决定,如果增加过多,会产生多个小文件。
1.增加map的个数,可以通过设置切片信息大小,因为一般一个切片启动一个maptask。如下公司每个block的大小是128Mb,所以我们可以将 set mapred.max.split.size 成64Mb.这样一个块用两个task执行。
hive>set dfs.block.size;
dfs.block.size=134217728
2.增加reduce数量 可以通过:set hive.exec.reducers.bytes.per.reducer配置
6.所以分析了一下,实际公司开发中,配到这种情况,重启集群也不太靠谱的情况下,只能检查优化一下自己的程序了。
1.一般可以给任务设置失败重试次数,自动多试几次可能会成功。
2.检查程序是否有数据倾斜的问题,一般来说大多数这种情况都是数据倾斜造成的。除非是公司的集群参数配置的不合理,那么可以修改一下,适当按照上面的情况增加一下值。