有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

我们有一个运行CDH5的四个datanodes集群。0.2,通过Cloudera Manager包裹安装。 为了将1300万用户的行导入HBase,我们编写了一个简单的Python脚本,并使用hadoop streaming jar。它可以按预期工作,最多可工作10万行。然后。。。然后,所有datanodes一个接一个地崩溃,并显示相同的消息:

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使用创建监视器。我们最终会的,但我想知道,将1300万行导入到HBase中会导致所有区域服务器崩溃的可能性有多大。有干净的解决办法吗

编辑:

数据节点上的JVM选项包括:

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

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

下面是我们运行的Python脚本的摘录。我们填充了两个表:一个表中有一个唯一的用户ID作为rowkey,另一个表中有一个包含用户信息的columnfamily,另一个表中有我们可能希望作为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)

共 (1) 个答案

  1. # 1 楼答案

    现在很多人都遇到的一个主要问题是,java应用程序可用的RAM数量激增,但关于调优java GC的大部分信息都基于32位时代的经验

    我最近花了大量时间研究大型堆情况下的GC,以避免可怕的“长暂停”。我看了几遍这个excellent presentation,最后GC和我所面临的问题开始变得更有意义

    我对Hadoop知之甚少,但我认为你们可能会遇到这样的情况:你们的年轻一代太小了。不幸的是,关于JVM GC调优的大多数信息都没有强调,对象GC的最佳位置是年轻一代。此时收集垃圾几乎不需要时间。我不会详细介绍(如果你想知道的话,请观看演示文稿),但是如果你的年轻一代(新一代)没有足够的空间,它就会过早地填满。这将强制收集,一些对象将被移动到终身(旧)世代。最终,终身制的一代人会被填满,也需要被收集起来。如果你的终身世代中有很多垃圾,这可能会非常慢,因为终身收集算法通常是mark sweep,它收集垃圾的时间不为零

    我认为你正在使用热点。下面是hotspot的各种GC参数的一个很好的参考JVM GC options

    首先,我会大大增加年轻一代的规模。我在这里的假设是,许多短到中等寿命的对象正在被创建。你想要避免的是将这些人提升为终身制的一代。这样做的方式是延长他们在年轻一代身上的时间。要实现这一点,您可以增加它的大小(因此填充所需的时间更长),也可以增加使用期限阈值(本质上是对象将停留的时间)。使用寿命阈值的问题是,在年轻一代中移动物体需要时间。在记忆方面,增加年轻一代的规模是低效的,但我猜你有很多空闲的

    我将此解决方案用于缓存服务器,在>;100毫秒范围和不频繁(每天少于一次)的主要收集通常在0.5秒以下,堆容量约为4GB。我们的目标可以存活5分钟、15分钟或29天

    另一件您可能要考虑的是G1(垃圾第一)收集器,它最近被添加到热点中。p>

    我想知道这个建议对你有多有效。祝你好运