我们有一个运行CDH5.0.2的四数据集,通过Cloudera包安装。为了将1300万用户的行导入HBase,我们编写了一个简单的Python脚本,并使用hadoop流jar。它可以像预期的那样工作,最多可达100 K行。然后..。然后,一个接一个地,所有的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,从而导致所有区域服务器的崩溃。有干净的解决办法吗?
编辑:
Datanodes上的JVM选项是:
-XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:-CMSConcurrentMTEnabled -XX:CMSInitiatingOccupancyFraction=70 -XX:+CMSParallelRemarkEnabled
Datanodes是运行CentOS 6.5的物理机器,每台机器都有32 at和2 2GHz带30 at高速缓存的1 1Quadcore。
下面是我们运行的Python脚本的摘录。我们填充两个表:一个表具有唯一的用户ID作为行键,一个列家族包含用户的信息,另一个表包含我们可能希望作为行键访问的所有信息。
#!/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)
发布于 2015-01-16 16:12:33
最近很多人遇到的主要问题之一是,java应用程序可用的RAM数量已经激增,但是关于调整Java的大部分信息都是基于32位时代的经验。
最近,为了避免可怕的“长暂停”,我花了大量的时间研究GC的大型堆情况。我看了几次这个出色的演讲,最后GC和我所面临的问题开始变得更有意义了。
我对Hadoop不太了解,但我认为你可能会遇到年轻一代太小的情况。遗憾的是,关于JVM GC调优的大多数信息都没有强调您的对象最好的位置是在年轻一代中。从字面上说,在这一点上收集垃圾完全不需要时间。我不会讲细节(如果你想知道的话,看演示稿),但会发生的是,如果你的年轻一代(新一代)没有足够的空间,它就会过早地被填满。这会强制集合,一些对象将被移动到永久(旧)代中。最后,终身的一代填补了,它将需要收集。如果你有很多垃圾在你的终身代,这可能是非常慢,因为终身收集算法通常是标记扫描,这是一个非零的时间收集垃圾。
我想你在使用Hotspot。以下是针对hotspot的各种GC参数的很好的参考。JVM GC选项
我首先要大大增加年轻一代的人数。我在这里的假设是,许多短期到中等寿命的对象正在被创建。你想要避免的是让这些被提升到终身代。你这样做的方式是延长他们在年轻一代身上的时间。要做到这一点,您可以增加它的大小(因此需要更长的时间来填充),也可以增加延长的阈值(实质上是对象将保留的年轻集合的数量)。延长门槛值的问题是,在年轻一代中,移动对象需要时间。在记忆方面,增加年轻一代的规模是没有效率的,但我猜你还有很多可省的。
我在缓存服务器时使用了这个解决方案,并且在> 100 ms范围内有少量的集合,并且很少(每天少于一次)主要的集合通常在0.5s以下,堆在4GB左右。我们的对象可以活5分钟、15分钟或29天。
您可能需要考虑的另一件事是G1 (垃圾优先)收集器,它最近被添加到HotSpot中(相对地说)。
我对这个建议对你有多好感兴趣。祝好运。
https://stackoverflow.com/questions/24556461
复制相似问题