SolrCloud 集群 ConcurrentLRUCache Full Gc 问题查找 即 JVM老年代无法回收
1.问题描述
jstat -gcutil 25477 1000
Solr JVM ,一直FUll GC,老年代对象一直存活,无法回收,初步分析: 使用 eclipse 插件 Memory Analysis Tools ( MAT )分析老年代 内存占用情况
2. 进行步骤
A.导出 内存快照
jmap -dump:format=b,file=/tmp/heap.hprof 25477
B.把 /tmp/heap.hprof 下载到本地,使用 MAT 进行分析
3.结果分析
从图中可以看出,org.apache.solr.util.ConcurrentLRUCache 对象竟然使用 10.8G的堆内存空间。
两个 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 内存使用情况
问题延伸:
1.此问题是由于缓存无法回收引起的,用过改天缓存大小解决
2.解决办法二: 增加弱引用的使用,使用 WeakHashMap 来存放缓存对象,及时清理缓存对象。
3. solr 内存会在索引预热阶段,清理缓存,当我们基于 lucene 做二次开发建立集群的时候,可以在预热阶段,自行清理WeakHashMap 缓存对象。