java—hadoop cdh5中的垃圾收集持续时间

m0rkklqb  于 2021-06-03  发布在  Hadoop
关注(0)|答案(1)|浏览(309)

我们有一个运行cdh5.0.2的四个datanodes集群,通过cloudera manager parcels安装。为了将1300万用户的行导入hbase,我们编写了一个简单的python脚本并使用hadoop流jar。它可以正常工作,最多10万行。然后。。。然后,一个接一个地,所有数据节点都会崩溃,并显示相同的消息:

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会导致所有区域服务器崩溃的可能性有多大。有没有干净的解决办法?
编辑:
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,一个表的columnfamine包含用户的信息,另一个表的所有信息都是我们可能希望作为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)
tquggr8v

tquggr8v1#

现在很多人遇到的一个主要问题是,java应用程序可用的ram数量激增,但是关于调优javagc的大部分信息都是基于32位时代的经验。
为了避免可怕的“长时间暂停”,我最近花了大量时间研究gc在大堆情况下的应用。我看了好几遍这篇精彩的演讲,终于gc和我所面对的问题开始变得更有意义了。
我对hadoop知之甚少,但我认为您可能会遇到这样一种情况:您的年轻一代太小了。不幸的是,关于jvmgc调优的大多数信息都没有强调,对象gc的最佳位置是在年轻一代。在这一点上收集垃圾根本不需要时间。我不想谈细节(如果你想知道的话,请看演示稿),但是如果你的年轻一代没有足够的空间,它就会过早地被填满。这将强制集合,并且某些对象将移动到终身(旧)代。最终,终身教龄的一代人将填补,它将需要收集太多。如果在终身生成中有大量垃圾,这可能会非常慢,因为终身收集算法通常是mark-sweep,其收集垃圾的时间不为零。
我想你用的是热点。这里有一个很好的关于hotspot的各种gc参数的参考。jvm gc选项
我将从大大增加年轻一代的规模开始。我在这里的假设是,正在创建许多中短命的对象。你要避免的是把他们提升为终身一代。你这样做的方式是延长他们在年轻一代的时间。要实现这一点,您可以增加它的大小(因此填充它需要更长的时间)或增加保持阈值(基本上是对象将保留的年轻集合数)。使用寿命阈值的问题是,在年轻一代中移动物体需要时间。增加年轻一代的规模在记忆方面是低效的,但我猜你有很多多余的。
我在缓存服务器上使用过这个解决方案,我有>100ms范围内的小集合和不常见(每天少于一个)的大集合,通常在0.5s以下,堆大约为4gb。我们的目标可以活5分钟,15分钟或29天。
您可能需要考虑的另一件事是g1(垃圾优先)收集器,它是最近添加到hotspot的(相对而言)。
我对这个建议对你的效果很感兴趣。祝你好运。

相关问题