对 HBase 表进行批量放入时出现 RejectedExecutionException

发布于 2024-12-01 10:03:06 字数 728 浏览 2 评论 0原文

我正在尝试将行批量放入 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)

非常感谢任何帮助!

I am trying to put rows into HBase (0.90.0) in batches of size ~ 1000 (rows) I have multiple producer threads writing data into a queue, and a single consumer thread which wakes up every couple of minutes, and writes everything that's in the queue to HBase as a batch. However, I am getting the following exception , and I'm not sure what this means.

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)

Any help is greatly appreciated!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

硬不硬你别怂 2024-12-08 10:03:06

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

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

这个 Jira 更深入地介绍了这个错误:https://issues.apache.org/jira /browse/HBASE-3692

因此,请检查您的代码,搜索对 close() 的调用,然后删除它们,或者根据需要将其替换为 flushCommits()到。我遇到了与您相同的问题,删除不必要的 htable.close() 调用足以避免该问题。

If you can, avoid doing Put or other operations on a HTable that has been close()'d in the past.

Normally there is no strong reason for doing htable.close() in the middle of your code, a htable.flushCommits() might be enough. Try reserving htable.close() as a finalizing step, when your code will not use HBase anymore.

This Jira goes deeper in details about this bug: https://issues.apache.org/jira/browse/HBASE-3692

So inspect your code, searching for calls to close() and either remove them or substitute it with flushCommits() if you need to. I've ran into the same problem you did, and removing the unnecessary htable.close() calls was enough to avoid the problem.

邮友 2024-12-08 10:03:06

几个月来,我一直在使用 CDH 4.7 中的 HBase 0.94.15 的代码中寻找一个非常类似的错误,今晚我终于找到了该错误的原因。它似乎已在最新的 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 并开始使用它

我们的修复方法是删除第二个 close() 在台球桌上。不再有 RejectedExecutionException

最新 HBase 检查池化表接口是否已关闭,如果是,则不会再次关闭包装表。它还会引发异常,该异常仍然不符合 Java Closeable 接口,但那是另一回事了。

I have been chasing a very similar bug for months in our code using HBase 0.94.15 in CDH 4.7 and tonight I finally found the reason for the bug. It seems fixed in latest HBase, so a quick workaround would be to upgrade.

The problem was an improper implementation of HTablePool.PooledHTable.close(). Java's Closeable interface says calling close() more than once has no affect. However, if you follow the code, you'll see pooled table interfaces do not follow this rule and closing them a second time actually puts the wrapped table back in the pool again. At the time of the second close, the actual wrapped table might be in use in another thread. That can cause a connection to be closed while being used, or even another thread accessing the same wrapped table.

  1. Thread A gets table T from the pool
  2. Thread A closes table T
  3. Thread B gets table T from the pool
  4. Thread A closes table T again (and HTablePool.PooledHTable.close() doesn't complain)
  5. Thread B starts using table T
  6. Table T is marked as not being used and either:
    • Pool decides table T has not been used for long enough and can be really closed
    • Thread C gets table T from the pool and starts using it

The fix for us was to remove that second close() on the pooled table. No more RejectedExecutionException!

Latest HBase checks if the pooled table interface was already closed, and if so doesn't close the wrapped table again. It also throws an exception, which still doesn't conform to the Java Closeable interface, but that's another story.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文