java hbase多线程_多线程读写HBase的一个注意点

本文分析了一个Java程序在使用HBase进行多线程读写时遇到的`OutOfMemoryError`问题,指出在每个HTable初始化时会创建线程池,可能导致大量线程占用资源。解决方案包括合理设置Container数和线程数,使用HTablePool管理HTable实例,以及自定义线程池限制并发。最后提到了加大系统可创建线程数的参数调整。
摘要由CSDN通过智能技术生成

http://www.searchtb.com/2014/03/two-hbase-bugfix.html

1

2

3

4

5

6

7

8

java.util.concurrent.ExecutionException:

java.lang.RuntimeException: java.lang.OutOfMemoryError: unable to

create new native

thread

at

java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:222)

at

java.util.concurrent.FutureTask.get(FutureTask.java:83)

at

org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.processBatchCallback(HConnectionManager.java:1604)

at

org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.processBatch(HConnectionManager.java:1456)

at

org.apache.hadoop.hbase.client.HTable.flushCommits(HTable.java:1011)

at

org.apache.hadoop.hbase.client.HTable.put(HTable.java:834)

at

com.taobao.dump.sapclient.client.HbaseClient.set(HbaseClient.java:224)

看错误信息,不能建立新的线程,和之前集群升级时遇到的一个问题类似,分析是某个程序建了大量的线程,达到了系统的上限。看机器上跑的进程的,最大可能是这个程序自己。从出错信息分析,结合hbase源码,在每个htable建立的时候,会初始化一个线程池。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

int maxThreads =

conf.getInt("hbase.htable.threads.max",

Integer.MAX_VALUE);

if (maxThreads ==

0) {

maxThreads

= 1; // is there a better

default?

}

long keepAliveTime =

conf.getLong("hbase.htable.threads.keepalivetime",

60);

// Using the "direct handoff" approach, new threads will

only be created

// if it is necessary and will grow unbounded. This

could be bad but in HCM

// we only create as many Runnables as there are region

servers. It means

// it also scales when new region servers are

added.

this.pool = new

ThreadPoolExecutor(1,

maxThreads,

keepAliveTime,

TimeUnit.SECONDS,

new

SynchronousQueue(),

Threads.newDaemonThreadFactory("hbase-table"));

((ThreadPoolExecutor)this.pool).allowCoreThreadTimeOut(true);

这个pool的作用是client在提交一个操作时,会建立一个callable线程提交到pool里,每个线程专门处理各自

regionserver上的请求,最终聚合在一起,返回给client。所以当一个批量操作的请求过来的时候,极端情况下会在每个

regionserver都会有一个线程,而每个htable都独自维护这个pool。所以当进程里htable实例多,并且集群规模较大的时候,该进程

的线程数极端情况下是很多的。

具体到这个程序,确实有大量的batch操作,并且开了29个处理线程,并且hbase集群加了一批机器后,达到了近400台的规模,那极端情况下,将有1万多个线程,还不包括其他处理线程。而当时又有多个进程被同时调度到这台机器上,这时就就会出现上述异常了。

解决思路应用层面主要是降低极端情况下的并发,有以下几个方面:

1,container数和单个container中的线程数,在并发处理能力保持不变的情况下,选择合理的container数和线程数。

2,使用HTablePool来统一管理HTable实例,最好是单例,并且设定一个合理的maxSize,如并发时htable实例不够,调用方就先等待,直到有可用的实例。

3,建立htable对象时,指定自己的线程池,这个线程池全局共用,并且维护一个有界队列,当队列满时,请求就等待。

1

2

public

HTable(Configuration conf,final

byte[] tableName,

final ExecutorService

pool)

这个case最后的解决方式是,调低了HTablePool的maxSize。

另一个解决思路,加大系统可创建的最大线程数,关于一个JVM进程最多可以创建多少个线程,请参考 http://jzhihui.iteye.com/blog/1271122 ,但在我们的环境实际测试,只有调整参数/proc/sys/vm/max_map_count才能加大可创建的线程数。如不做调整,则可创建30000+个线程。具体系统层面的因果还待进一步分析。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值