概況:
生產環境HBase集群內存經常處於高位(90%),而且GC之后也是內存依然處於高位,經分析內存全部由集群的regionserver進程所持有,,經常重啟之后,大概3-4天就會保持在高位。由上述症狀,可以判斷集群內存有泄露的嫌疑。
分析
1、先熟悉一下HBase的內存模型
HBase系統中有兩塊大的內存管理模塊,一塊是MemStore ,一塊是BlockCache,前置是用於集群寫入所屬內存,而后者用於緩存熱數據,提供查詢速度。這兩者均可以通過配置文件進行配置。當前集群均配置了0.4和0.4的比例。而考慮到HBase集群是多寫少讀的情景,為此而引入了MSLAB機制來優化HBase的MemStore 負擔。內存的使用率會呈現很優美的鋸齒圖形。
2、分析內存使用率和業務關系
起初認為是讀寫業務量已經超過了集群負載能力,但集群業務也不大,寫和讀的TPS,帶寬吞吐量均未達到集群限定的能力,而且CPU利用率大多半都被GC占用,但內存就是持高不下,即使業務了停了一天,內存還是不怎么下降,很明顯和業務量無關。
那么和compaction有關?經觀察的確可以看compact時特別消耗時間。此時感覺看到了希望,調整各個參數,把compact操作提升了10+倍之后,內存還是持高不下 。剩下最根治的辦法就是分析內存,看一下內存數據都是什么?有無內存泄露問題。
3、分析dunp文件
節點dump下regionserver的內存,分析發現內存中有50個RpcServer.FifoRWQ.default.read.handler線程,每個線程持有了1.2%左右的總內存,那么所有的線程持有的內存占有量大於為50*1.2%=60%。隨着查詢次數增多,線程持續的內存還會持續增加,如下圖。
分析每一個線程持有的內存數據,全部都是業務信息。
那么繼續分析,此業務信息所屬對象:org.locationtech.geomesa.filter.factory.FastFilterFactory。而對比同規模的集群,的確是此異常集群開啟了GeoMesa特性。找到問題所在,那就看源碼分析是唯一出路。
解決方案
經分析GeoMesa源碼,緩存數據為GeoMesa的filterCache,全部都是查詢的條件及其優化后查詢條件。如下代碼:
override def getOrElseUpdate(key: K, op: => V): V = { val cached = caches.get.getIfPresent(key) if (cached != null) { cached } else { val value = op
//value=optimize(sft, ECQL.toFilter(ecql))
caches.get.put(key, value) value } }
導致集群隨着查詢次數增多,內存一直持續不下。
能否去掉此處緩存策略呢?為什么緩存此查詢信息呢,目的就是為了減少同樣的查詢再次被優化的步驟。那么我們查詢添條件key有沒有重復使用,此處有個嚴格規定,就是key中不僅保證使用相同的GeoMesa函數還有使用相同的參數,基於這個原則,業務上查詢條件是沒有重復的。
我們配置了可選參數useFilterCache,默認是開啟的,沒必要緩存此查詢條件,應予以刪除。
結論
在配置文件中添加了useFilterCache參數,默認是開啟的,根據業務需要選擇開始和關閉filterCache特效。
經分析我們業務場景沒必要緩存此查詢條件,,應予以關閉。優化后的集群內存使用率情況就恢復了正常狀態。