编程语言
首页 > 编程语言> > java – Hadoop CDH5中的垃圾收集持续时间

java – Hadoop CDH5中的垃圾收集持续时间

作者:互联网

我们有一个运行CDH5.0.2的四数据节点集群,通过Cloudera Manager parcel安装.
为了将13M用户的行导入HBase,我们编写了一个简单的Python脚本并使用了hadoop-streaming jar.它的工作效果可达100k行.然后……然后,一个接一个地,所有数据节点都崩溃了相同的消息:

The health test result for REGION_SERVER_GC_DURATION  has become bad: 
Average time spent in garbage collection was 44.8 second(s) (74.60%) 
per minute over the previous 5 minute(s). 
Critical threshold: 60.00%.

在网络上发现的建议之后解决问题的任何尝试(例如, [1], [2], [3])都不会导致任何接近解决方案的问题.使用java堆大小“玩”是没用的. “解决”这种情况的唯一方法是将区域服务器的垃圾收集持续时间监控周期从5’增加到50′.可以说是一个肮脏的解决方法.

我们目前没有工作人员为我们的GC使用创建监视器.我们最终会这样做,但我想知道如何将13M行导入HBase可能会导致所有区域服务器崩溃.有清洁的解决方案吗?

编辑:

Datanodes上的JVM选项是:

-XX:UseParNewGC -XX:UseConcMarkSweepGC -XX:-CMSConcurrentMTEnabled -XX:CMSInitiatingOccupancyFraction = 70 -XX:CMSParallelRemarkEnabled

Datanodes是运行CentOS 6.5的物理机器,每个都有32Gb Ram和1Quadcore,2GHz,30Mb缓存.

下面是我们运行的Python脚本的摘录.我们填写两个表:一个表具有唯一的用户ID作为rowkey,一个列具有用户的信息,另一个表包含我们可能想要作为rowkey访问的所有信息.

#!/usr/bin/env python2.7
import sys
import happybase
import json
connection = happybase.Connection(host=master_ip)
hbase_main_table = connection.table('users_table')
hbase_index_table = connection.table('users_index_table')
header = ['ID', 'COL1', 'COL2', 'COL3', 'COL4']
for line in sys.stdin:
    l = line.replace('"','').strip("\n").split("\t")
    if l[header.index("ID")] == "ID":
        #you are reading the header
        continue
    for h in header[1:]:
        try:
            id = str(l[header.index("ID")])
            col = 'info:' + h.lower()
            val = l[header.index(h)].strip()
            hbase_table.put(id_au_bytes, {
                    col: val
                    })
            indexed = ['COL3', 'COL4']
            for typ in indexed:
               idx = l[header.index(typ)].strip()
               if len(idx) == 0:
                   continue
               row = hbase_index_table.row(idx)
               old_ids = row.get('d:s')
               if old_ids is not None:
                   ids = json.dumps(list(set(json.loads(old_ids)).union([id_au])))
               else:
                   ids = json.dumps([id_au])
               hbase_index.put(idx, {
                       'd:s': ids,
                       'd:t': typ,
                       'd:b': 'ame'
                       })
       except:
           msg = 'ERROR '+str(l[header.index("ID")])
           logging.info(msg, exc_info=True)

解决方法:

许多人目前遇到的主要问题之一是Java应用程序可用的RAM量已经爆炸,但是有关调优Java GC的大部分信息都是基于32位时代的经验.

我最近花了大量时间研究GC的大堆情况,以避免可怕的“长时间停顿”.我几次看了这个excellent presentation,最后GC和我遇到的问题开始变得更有意义了.

我对Hadoop的了解不多,但我认为你可能会遇到年轻一​​代太小的情况.这很不幸,但大多数有关JVM GC调优的信息都没有强调,对象是GC的最佳位置是年轻一代.在这一点上,根本没有时间收集垃圾.我不会详细介绍(如果你想知道的话,请观看演示文稿)但是如果你的年轻(新一代)没有足够的空间,它会过早地填满.这会强制收集,一些对象将被移动到终身(旧)代.最终,终身一代填满了,也需要收集.如果您的终身代中有大量垃圾,这可能会非常缓慢,因为终身收集算法通常是标记扫描,其收集垃圾的时间非零.

我认为你正在使用Hotspot.这里是热点的各种GC参数的一个很好的参考. JVM GC options

我首先要大大增加年轻一代的规模.我的假设是,正在创建许多短到中等生命的对象.你想要避免的是将这些提升到终身一代.你这样做的方式是延长他们在年轻一代中度过的时间.要实现这一点,您可以增加它的大小(因此需要更长的时间来填充)或增加时效阈值(基本上是对象将保留的年轻集合的数量).暂停阈值的问题在于在年轻一代中移动对象需要时间.增加年轻一代的规模在记忆方面是低效的,但我的猜测是你有很多余地.

我已将此解决方案与缓存服务器一起使用,并且我在>中使用了少量集合. 100毫秒范围和不常见(少于一天)主要收藏品通常低于0.5秒,堆积约4GB.我们的目标是5分钟,15分钟或29天.

您可能想要考虑的另一件事是G1(垃圾优先)收集器,它最近被添加(相对而言)到HotSpot.

我对这个建议对你有多好感兴趣.祝好运.

标签:java,garbage-collection,hadoop,hbase,cloudera-cdh
来源: https://codeday.me/bug/20190629/1321203.html