关于mapreduce的topN的问题

来源:互联网 发布:日语学习软件 编辑:程序博客网 时间:2024/06/06 16:50

前段时间有位同事的mr在集群上时而通过时而挂掉, 错误是

2015-12-28 11:13:26,013 INFO [main] org.apache.hadoop.mapred.Merger: Down to the last merge-pass, with 2 segments left of total size: 1640163582 bytes2015-12-28 11:13:26,096 INFO [main] org.apache.hadoop.conf.Configuration.deprecation: mapred.skip.on is deprecated. Instead, use mapreduce.job.skiprecords2015-12-28 11:17:39,744 WARN [IPC Client (2008966511) connection to BJ-PRESTO-200083.jd.com/172.16.200.83:8020 from mart_cmo] org.apache.hadoop.ipc.Client: Unexpected error reading responses on connection Thread[IPC Client (2008966511) connection to BJ-PRESTO-200083.jd.com/172.16.200.83:8020 from mart_cmo,5,main]java.lang.OutOfMemoryError: GC overhead limit exceeded2015-12-28 11:17:39,745 FATAL [main] org.apache.hadoop.mapred.YarnChild: Error running child : java.lang.OutOfMemoryError: GC overhead limit exceeded

最初定位为reduce的内存溢出, reduce代码中内存一直未释放,导致内存不足.

任务中,也显示reduce数量是1, 于是寻问job的业务含义, 其实是一个约几十T数据的全排序TOPN.(top前百万)

然后查看相关代码发现, reduce中,有一个list收集数据, 并排序,最后写出数据, 导致内存没有释放, 

参考代码:

reduce:   list.add(值)cleanup():   list.sort()   write (list)

解决方法其实很多, 通常的解决方法, 是reduce中依然维护list的top,每次都只是存留前topN, cleanup写出:

参考代码

reduce:    list.add(值)    list.sort().remove(index > topN)cleanup():   write (list)

但是,以上思路,是我时常处理方式,但是需求有些特殊, topN可能是百万,甚至千万, 依然会有gc回收不了, 内存不释放的问题.

如果topn的需要量级增加, 则可能任务就会失败.

比较low的方法:, mr链解决, 这个比较简单就不说了,.

比较合适的方法:

job.partion=TotalOrderPartitionermap:  write(-top ,value)reduce:  if [成员变量i ++ < topN]    write(top,value)


TotalOrderPartitioner是类似分区表的范围分区, 但是是递增排序, map取负值是key是倒序,故此相对之前写法反而简单很多,也无需担心jvm负载的问题.



0 0
原创粉丝点击