在对HBase表进行批量处理时,RejectedExecutionException

时间:2011-08-24 22:23:05

标签: hbase

我试图将行放入HBase(0.90.0)中,批量大小为1000(行)我有多个生产者线程将数据写入队列,并且每隔几分钟唤醒一个消费者线程,将队列中的所有内容写入HBase作为批处理。但是,我得到以下异常,我不确定这意味着什么。

Caused by: java.util.concurrent.RejectedExecutionException
    at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:1760)
    at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:767)
    at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:658)
    at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:92)
    at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.processBatch(HConnectionManager.java:1135)

非常感谢任何帮助!

2 个答案:

答案 0 :(得分:5)

如果可以,请避免对过去曾Put d的HTable执行close()或其他操作。

通常没有充分理由在代码中间执行htable.close()htable.flushCommits()可能就足够了。当您的代码不再使用HBase时,请尝试保留htable.close()作为最终确定步骤。

本Jira详细介绍了这个错误:https://issues.apache.org/jira/browse/HBASE-3692

请检查您的代码,搜索对close()的来电,然后将其删除或在需要时将其替换为flushCommits()。我遇到了你遇到的同样问题,删除不必要的htable.close()电话就足以避免这个问题了。

答案 1 :(得分:1)

我在我们的代码中使用HBH 0.94.15在CDH 4.7中追踪了一个非常类似的bug,今晚我终于找到了这个bug的原因。它似乎已在最新的HBase中修复,因此快速解决方法是升级。

问题是HTablePool.PooledHTable.close()的执行不当。 Java的Closeable界面说多次调用close()没有任何影响。但是,如果您遵循代码,您将看到池化的表接口不遵循此规则,并且第二次关闭它们实际上会将包装的表重新放回池中。在第二次关闭时,实际的包装表可能正在另一个线程中使用。这可能导致在使用时关闭连接,甚至是访问同一个包装表的另一个线程。

  1. 线程A从池中获取表T
  2. 线程A关闭表T
  3. 线程B从池中获取表T
  4. 主题A再次关闭表格T(而HTablePool.PooledHTable.close()并未抱怨)
  5. 线程B开始使用表T
  6. 表T标记为未使用,并且:
    • 池决定表T的使用时间不够长,可以真正关闭
    • 线程C从池中获取表T并开始使用它
  7. 我们的解决方法是删除合并表上的第二个close()。不再RejectedExecutionException

    最新HBase checks如果池表接口已经关闭,如果是,则不会再次关闭包装表。它还抛出了一个异常,它仍然不符合Java Closeable接口,但那是另一个故事。