HBase-2.0.3 & HBase-2.1.1版本記憶體洩漏

weixin_34208283發表於2018-12-16

HBase Committer胡爭提出的issue:
[HBASE-21551]Memory leak when use scan with STREAM at server side
https://issues.apache.org/jira/browse/HBASE-21551

6739367-6558fc262da5c236

問題摘要
通常順序掃描的時候。為了可以避免頻繁的Position Read,服務端採用STREAM型別。如果出現以下任何一種情況,由於洩漏導致的記憶體不足錯誤,HBase叢集將遇到Region Server故障:
1.使用者發起設定為使用STREAM讀取型別的Scan操作;
2.使用者發起設定為使用預設讀取型別,讀取掃描中涉及的超過4倍列族塊大小(例如,預設為4 * 64KiB)的Scan操作;
3.執行Compaction。
問題描述
我們使用STREAM開啟RegionServerScanner,如下所示:

RegionScannerImpl#initializeScanners
      |---> HStore#getScanner
                    |----------> StoreScanner()
                                        |-------> StoreFileScanner#getScannersForStoreFiles
                                                          |------> HStoreFile#getStreamScanner      #1

在#1中,將StoreFileReader放入ConcurrentHashMap streamReaders,但是在關閉StoreFile之前不會從streamReaders中刪除StreamReader。
因此,如果使用流掃描很多次,則會展開HashMap streamReaders,通過heap-dump檢視堆儲存情況:

6739367-0f6c1d7ec35df6bf

胡爭發現此錯誤,因為當通過在叢集中使用YCSB(RS的堆大小為50g)對掃描效能進行基準測試時,RS很容易在很長時間內Full GC(~110秒)。
根本原因
當有長時間執行的掃描時,Region Server程式會嘗試使用面向順序訪問的不同API來優化訪問。由於HBASE 2.0+的HBASE-20704錯誤,因此當掃描完成時Region Server無法釋放相關資源。 HBase內部檔案壓縮過程始終使用相同的優化路徑。
解決方法
升級到最新版本。通過將配置值“hbase.storescanner.pread.max.bytes”設定為MAX_INT可以最大限度地減少對此錯誤的影響,以避免對預設使用者掃描進行優化。並且應該檢查客戶端以確保它們不會將STREAM讀取型別傳遞給Scan API。這將對長時間Scan的效能產生嚴重影響。
壓縮總是使用這種順序優化的讀取機制,因此下游使用者需要在壓縮發生後定期重新啟動Region Server角色。
修復實現
https://github.com/apache/hbase/commit/3b854859f6fad44cbf31164374569a6ab23f3623
https://github.com/apache/hbase/commit/67ab8b888f8b393979624a2bd7d527fefd9dd6d7
6739367-2124a0194a632a9d

在此感謝HBase Committer胡爭Review細節。

相關文章