2011-08-24 62 views
4

我試圖把行放入HBase(0.90.0)批量的大小〜1000(行)我有多個生產者線程寫入數據到一個隊列和一個消費者線程每隔幾分鐘就會喚醒一次,並將隊列中的所有內容寫入HBase作爲批處理。但是,我收到以下異常,我不確定這意味着什麼。RejectedExecutionException當批量放入一個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.90.3+(+表示Cloudera口味的HBase),看看它是否會持續下去。否則,看起來好像你試圖在一個關閉/停止的ExecutorThreadPool中執行一個線程。看到創建「放入HBase」的代碼會很有幫助。 – Tony

回答

4

如果可以,請避免在過去對HTable進行Put或其他操作時使用close()'d。

通常沒有理由在你的代碼中間做htable.close()htable.flushCommits()可能就足夠了。嘗試保留htable.close()作爲最終確定步驟,當您的代碼不再使用HBase時。

這吉拉在有關此錯誤信息的不斷深入:https://issues.apache.org/jira/browse/HBASE-3692

所以,檢查你的代碼,搜索呼叫close(),要麼刪除,或者如果您需要與flushCommits()代替它。我遇到了同樣的問題,並且刪除不必要的htable.close()調用足以避免此問題。

1

我在我們的代碼中使用HBase 0.94.15在CDH 4.7中搜索了一個非常類似的bug,今晚我終於找到了bug的原因。它在最新的HBase中似乎是固定的,所以快速的解決方法是升級。

問題在於HTablePool.PooledHTable.close()的執行不當。 Java的Closeable接口說不止一次調用close()沒有任何影響。但是,如果您遵循代碼,則會看到池表接口不遵循此規則,並且再次關閉它們實際上會將包裝的表再次放回池中。在第二次關閉時,實際包裝表可能正在另一個線程中使用。這可能導致連接在使用時被關閉,甚至會導致另一個線程訪問相同的包裝表。

  1. 線程A從池中
  2. 線程A關閉表T得到表T
  3. 線程B從池中
  4. 線程A再次關閉表T(和HTablePool.PooledHTable.close()不抱怨)獲取表T
  5. 線程B開始使用表T
  6. 表T被標記爲不被使用,並且:
    • 普爾決定噸能夠T尚未被使用足夠長的時間,並且可以真正關閉
    • 線程C-從池中獲取表T,並使用它

我們的修復是消除在該第二close()開始合併桌子。沒有更多RejectedExecutionException

最新的HBase checks如果池表接口已經關閉,並且如果沒有再次關閉包裝表。它也會拋出一個異常,它仍然不符合Java Closeable接口,但這是另一回事。