SolrCloud 集群 ConcurrentLRUCache Full Gc 问题查找 即 JVM老年代无法回收

1.问题描述


jstat -gcutil   25477  1000

SolrCloud 集群 ConcurrentLRUCache Full Gc 问题查找 即 JVM老年代无法回收

Solr  JVM ,一直FUll  GC,老年代对象一直存活,无法回收,初步分析: 使用 eclipse 插件  Memory  Analysis Tools ( MAT )分析老年代 内存占用情况

SolrCloud 集群 ConcurrentLRUCache Full Gc 问题查找 即 JVM老年代无法回收

2.  进行步骤

       A.导出  内存快照

        jmap -dump:format=b,file=/tmp/heap.hprof  25477

        SolrCloud 集群 ConcurrentLRUCache Full Gc 问题查找 即 JVM老年代无法回收

     B.把  /tmp/heap.hprof  下载到本地,使用  MAT 进行分析

3.结果分析

SolrCloud 集群 ConcurrentLRUCache Full Gc 问题查找 即 JVM老年代无法回收

SolrCloud 集群 ConcurrentLRUCache Full Gc 问题查找 即 JVM老年代无法回收

SolrCloud 集群 ConcurrentLRUCache Full Gc 问题查找 即 JVM老年代无法回收SolrCloud 集群 ConcurrentLRUCache Full Gc 问题查找 即 JVM老年代无法回收

SolrCloud 集群 ConcurrentLRUCache Full Gc 问题查找 即 JVM老年代无法回收

    从图中可以看出,org.apache.solr.util.ConcurrentLRUCache  对象竟然使用  10.8G的堆内存空间。

SolrCloud 集群 ConcurrentLRUCache Full Gc 问题查找 即 JVM老年代无法回收

      两个 ConcurrentLRUCache  对象 object  占用 20G的内存,堆内存 一共30G,这是内存无法接受。

4.问题解决及理论

      A. Lucene 有两种缓存   FieldCache   和 Filter Cache ,Solr 在lucene 又增加 queryResult、DocumentCache 和  perSegFilter (自定义缓存) ,一份  solr  JVM索引 对应的缓存 value ,都存放在 ConcurrentLRUCache 的   private final ConcurrentHashMap<Object, CacheEntry<K,V>> map 里。

           解决方案:

修改响应的size 的大小,观察几天JVM 内存使用情况

SolrCloud 集群 ConcurrentLRUCache Full Gc 问题查找 即 JVM老年代无法回收

SolrCloud 集群 ConcurrentLRUCache Full Gc 问题查找 即 JVM老年代无法回收


SolrCloud 集群 ConcurrentLRUCache Full Gc 问题查找 即 JVM老年代无法回收

问题延伸:

             1.此问题是由于缓存无法回收引起的,用过改天缓存大小解决

             2.解决办法二: 增加弱引用的使用,使用 WeakHashMap  来存放缓存对象,及时清理缓存对象。

             3. solr 内存会在索引预热阶段,清理缓存,当我们基于 lucene 做二次开发建立集群的时候,可以在预热阶段,自行清理WeakHashMap  缓存对象。