Solr学习笔记 - 关于cache
原本以为cache多缓存一些,提高命中率,不是美哉。所以看到之前solrconfig里面的filterCache、queryResultCache、documentCache还有ltr feature cache,就想把他调大。缓存的多了,提高命中,看着应该能提高性能才对。
下面开始做实验:
调整LRUCache为FastLRUCache、增加documentCache和queryResultCache的size
代码语言:txt复制 <!--
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。
代码语言:txt复制SolrCache<Query,DocSet> filterCache;
代码语言:txt复制<filterCache class="solr.FastLRUCache"
size="512"
initialSize="512"
autowarmCount="64"/>
queryResultCache
对Query的结果进行缓存,主要在SolrIndexSearcher类getDocListC方法中被使用
代码语言:txt复制SolrCache<QueryResultKey,DocList> queryResultCache;
代码语言:txt复制 <queryResultCache class="solr.LRUCache"
size="512"
initialSize="512"
autowarmCount="0"/>
documentCache
documentCache是用来保存<docid,document>
代码语言:txt复制 <documentCache class="solr.LRUCache"
size="512"
initialSize="512"
autowarmCount="0"/>
fieldValueCache
代码语言:txt复制SolrCache<String,UnInvertedField> fieldValueCache;
代码语言:txt复制<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。