Solr学习笔记 - 关于cache

时间:2022-07-22
本文章向大家介绍Solr学习笔记 - 关于cache,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

Solr学习笔记 - 关于cache

原本以为cache多缓存一些,提高命中率,不是美哉。所以看到之前solrconfig里面的filterCache、queryResultCache、documentCache还有ltr feature cache,就想把他调大。缓存的多了,提高命中,看着应该能提高性能才对。

下面开始做实验:

调整LRUCache为FastLRUCache、增加documentCache和queryResultCache的size

 <!--
 Query Result Cache
     Caches results of searches - ordered lists of document ids
     (DocList) based on a query, a sort, and the range of documents requested.
     Additional supported parameter by LRUCache:
        maxRamMB - the maximum amount of RAM (in MB) that this cache is allowed
                   to occupy
-->
<queryResultCache class="solr.FastLRUCache" size="102400" initialSize="10240" autowarmCount="0"/>

<!--
 Document Cache
     Caches Lucene Document objects (the stored fields for each
     document).  Since Lucene internal document ids are transient,
     this cache will not be autowarmed.

-->
<documentCache class="solr.FastLRUCache" size="102400" initialSize="10240" autowarmCount="0"/>

发现查询没有变好,反而开始抖动。从节点频繁掉点。耗时也开始抖动的厉害。如下图:

开始分析缓存的写入,结果突然发现,documentCache写入巨大,而命中又特别的低:

下面对solr的cache做一下具体分析

Solr的几个cache

filterCache

filterCache存储了fq的查询结果的文档id。多个fq查询是取结果交集。filterCache就是key为单个fq(类型为Query),value为document id集合(类型为DocSet)的cache。

SolrCache<Query,DocSet> filterCache;
<filterCache class="solr.FastLRUCache"
                     size="512"
                     initialSize="512"
                     autowarmCount="64"/>

queryResultCache

对Query的结果进行缓存,主要在SolrIndexSearcher类getDocListC方法中被使用

SolrCache<QueryResultKey,DocList> queryResultCache;
 <queryResultCache class="solr.LRUCache"
                          size="512"
                          initialSize="512"
                          autowarmCount="0"/>

documentCache

documentCache是用来保存<docid,document>

 <documentCache class="solr.LRUCache"
                       size="512"
                       initialSize="512"
                       autowarmCount="0"/>

fieldValueCache

SolrCache<String,UnInvertedField> fieldValueCache;
<fieldValueCache class="solr.FastLRUCache"
                            size="512"
                            autowarmCount="128"
                            showItems="32" />

Solr的cache种类

solr7版本时候的cache有两种FastLRUCache和LRUCache。从字面上看FastLRUCache岂不是最快的。那不应该都点换成FastLRUCache么。

FastLRUCache

FastLRUCache内部采用了ConcurrentLRUCache实现,而ConcurrentLRUCache内部又采用ConcurrentHashMap实现,所以是线程安全的。缓存通过CacheEntry中的访问标记lastAccessed来维护CacheEntry被访问的先后顺序。 即每当Cache有get或者put操作,则当前CacheEntry的lastAccessed都会变成最大的(state.accessCounter)。当FastLRUCache容量已满时,通过markAndSweep方式来剔除缓存中lastAccessed最小的N个项以保证缓存的大小达到一个acceptable的值。

在配置方面,FastLRUCache除了需要LRUCache的参数,还可有选择性的指定下面的参数:

1)minSize:当cache达到它的最大数,淘汰策略使其降到minSize大小,默认是0.9*size。

2)acceptableSize:当淘汰数据时,期望能降到minSize,但可能会做不到,则可勉为其难的降到acceptableSize,默认是0.95*size。

3)cleanupThread:相比LRUCache是在put操作中同步进行淘汰工作,FastLRUCache可选择由独立的线程来做,即通过配置cleanupThread来实现。当cache大小很大时,每一次的淘汰数据就可能会花费较长时间,这对于提供查询请求的线程来说就不太合适,由独立的后台线程来做就很有必要。

实现上,FastLRUCache内部使用了ConcurrentLRUCache来缓存数据,它是个加了LRU淘汰策略的ConcurrentHashMap,优点在于淘汰操作是O(1)的,缺点是需要对存取操作加互斥锁。

LRUCache

LRU又称最近最少使用。把缓存中的对象按访问的时间先后排序,当容量不足时,删除时间最早的。Solr中LRUCache是通过LinkedHashMap来实现的。实现上,LRUCache直接使用LinkedHashMap来缓存数据,由initialSize来限定cache的大小,淘汰策略也是使用LinkedHashMap内置的LRU方式,读写操作都是对map的全局锁

参数:

1)size:cache中可保存的最大项数,默认是1024

2)initialSize:cache初始化时容量大小,默认是1024。

3)autowarmCount:当切换SolrIndexSearcher时,可以对新生成的SolrIndexSearcher做autowarm(预热)处理。autowarmCount表示从旧的SolrIndexSearcher中取多少项来在新的SolrIndexSearcher中被重新生成,如何重新生成由CacheRegenerator实现。1.4版本的Solr中,这个autowarmCount只能取预热的项数,如果不指定该参数,则表示不做autowarm处理。

FastLRUCache 没有额外维护新的结构,可以由ConcurrentHashMap支持并发读,但put操作中如果需要淘汰数据,淘汰过程是O(n)的,因为整个过程不加锁,会影响该次put的性能。

结论:FastLRU由于淘汰策略问题写入会变慢,get快,适合小量数据,命中特别高的场景,queryResultCache和documentCache的写入量都特别大,这样淘汰的数量也会特别多,命中又很低,所以不应该使用FastLRU。