前言
solr的界面我们都见过,这里有一些统计数据,也就是缓存:
这些缓存是干啥用的,这些指标又是什么意思呢?
还有solr的配置文件内的这些参数该如何配置
<filterCache
class="solr.LRUCache"
size="512"
initialSize="512"
autowarmCount="128"/>
<queryResultCache
class="solr.LRUCache"
size="512"
initialSize="512"
autowarmCount="32"/>
<documentCache
class="solr.LRUCache"
size="512"
initialSize="512"
autowarmCount="0"/>
<queryResultWindowSize>50</queryResultWindowSize>
<queryResultMaxDocsCached>200</queryResultMaxDocsCached>
<enableLazyFieldLoading>true</enableLazyFieldLoading>
这些缓存在查询中承担什么角色?
正文
solr的缓存分很多类型,合理的缓存使用可以加速查询有助于我们优化搜索性能,缓存在搜索引擎内扮演着一个非常重要的角色,这里针对solr主要的几种缓存做一个介绍,并通过一些实战讲解缓存优化技巧。
SOLR缓存原理
缓存评价指标
其中 lookups 为当前cache 查询数,hitratio 为当前cache命中率,inserts为当前cache插入数,evictions为从cache中踢出来的数据个数,size 为当前cache缓存数, warmuptime为当前cache预热所消耗时间,而cumulative都为该类型Cache累计的查询,命中,命中率,插入、踢出的数目
要知道这些参数,我们首先要认识什么是LRU,LFU
通过对solr源码的分析,我们也可以知道LFU的一些原理
留个悬念,有人知道为啥这里是这样的吗
LRUCache
LRUCache可配置参数如下:
1)size:cache中可保存的最大的项数,默认是1024
2)initialSize:cache初始化时的大小,默认是1024。
3)autowarmCount:当切换SolrIndexSearcher时,可以对新生成的SolrIndexSearcher做autowarm(预热)处理。autowarmCount表示从旧的SolrIndexSearcher中取多少项来在新的SolrIndexSearcher中被重新生成,如何重新生成由CacheRegenerator实现。
查看Solr源码可以发现,在实现上,LRUCache直接使用LinkedHashMap来缓存数据,由initialSize来限定cache的大小,淘汰策略也是使用LinkedHashMap的内置的LRU方式,读写操作都是对map的全局锁,所以并发性效果方面稍差。
fastLRUcache
在配置方面,FastLRUCache除了需要LRUCache的参数,还可有选择性的指定下面的参数:
1)minSize:当cache达到它的最大数,淘汰策略使其降到minSize大小,默认是0.9*size。
2)acceptableSize:当淘汰数据时,期望能降到minSize,但可能会做不到,则可勉为其难的降到acceptableSize,默认是0.95*size,也可以这么理解,如果没有设置minSize,那么改值会替代之。
3)cleanupThread:相比LRUCache是在put操作中同步进行淘汰工作,FastLRUCache可选择由独立的线程来做,也就是配置cleanupThread的时候。当cache大小很大时,每一次的淘汰数据就可能会花费较长时间,这对于提供查询请求的线程来说就不太合适,由独立的后台线程来做就很有必要。
实现上,FastLRUCache内部使用了ConcurrentLRUCache来缓存数据,它是个加了LRU淘汰策略的ConcurrentHashMap,所以其并发性要好很多,这也是多数Java版Cache的极典型实现
策略:cache超出总大小即启动并发清除线程,至少淘汰数据到acceptableSize
SOLR查询缓存的种类及作用
filtercache
FilterCache中存储了无序的lucene document id集合,即FilterCache存储了一些无序的文档标识号(ID),这些ID并不是我们在schema.xml里配置的unique key,而是solr内部的一个文档标识。
该cache有3种用途:
1)filterCache存储了filter queries(“fq”参数 q查询不加入过滤器缓存)得到的document id集合结果,Solr中的query参数有两种,即q和fq。如果fq存在,Solr是先查询fq(因为fq可以多个,所以多个fq查询是个取结果交集的过程),之后将fq结果和q结果取并。在这一过程中,filterCache就是key为单个fq(类型为Query),value为document id集合(类型为DocSet)的cache。从后面的分析你将会看到对于fq为range query来说,filterCache将表现出其更有价值的一面。
2)filterCache还可用于facet查询
facet查询中各facet的计数是通过对满足query条件的document id集合(可涉及到filterCache)的处理得到的。因为统计各facet计数可能会涉及到所有的doc id,所以filterCache的大小需要能容下索引的文档数。
3)如果solfconfig.xml中配置了<useFilterForSortedQuery/>,即设置该参数为true的时候,那么还可以进行排序
官方文档中有这么一句
queryResultCache
顾名思义,queryResultCache是对查询结果的缓存,但是它缓存的是对应查询结果的solridset
documentCache
顾名思义,documentCache用来保存对的。
在一个查询器内,请求文档优先走查询器内文档缓存
再来看官方文档
autowarm
一个例子
一个试验
建议自己手动操作
试验:
1、清空缓存 重启 查询结果缓存1(自检)
2、执行UI查询,查询结果缓存加1 文档缓存加10
3、再次执行,时间下降 hitratio =0.5
4、q查询加入consult_count:0 查询 结果缓存+1
5、再次执行时间下降
6、q=*:* fq= consult_count:0 过滤器缓存+1
7、再次执行 查询缓存被命中 没有走过滤器
8、 fq= consult_count:0 fq= is_health:0
查询缓存没有 过滤器缓存命中加一
fieldcache
我们知道lucene保存了正向索引(docId-->field)和反向索引(field-->docId)。反向索引是搜索的核心,检索速度很快。但是如果我们需要快速由docId得到Field信息(比如按照某个字段排序,字段值的信息统计),由于需要磁盘读取,速度会比较慢。因此Lucene实现了fieldCache。
Lucene实现了各种类型Field的缓存:Byte,Short,Int,Float,Long……
fieldCache是Lucene内部的缓存,主要用于缓存Lucene搜索结果排序,比如按时间排序等。由于fieldCache内部利用数组来存储数据(可以参看FieldCacheImpl源码),而且数组的大小开的都是maxDoc,所以当数据量较大时,fieldCache是相当消耗内存的,所以很容易出现内存溢出问题
Linux 系统——文件cache
这里参考两篇博客
关于linux cache介绍
https://www.ibm.com/developerworks/cn/linux/l-cache/index.html
Drop_caches等系统参数介绍
https://www.kernel.org/doc/Documentation/sysctl/vm.txt
1、干掉pagecache缓存命令
To free pagecache:
echo 1 > /proc/sys/vm/drop_caches
To free reclaimable slab objects (includes dentries and inodes):
echo 2 > /proc/sys/vm/drop_caches
To free slab objects and pagecache:
echo 3 > /proc/sys/vm/drop_caches
注:page cache中包含的tmpfs和共享内存是不能通过drop_caches回收的
2、重启服务器后快速加载solr data到内存
快速加载solr data到linux cache命令
find ./server/solr/ -type f -exec cat {} \; > /dev/null
solr缓存调优
1、使用fastLRUcache 并指定cleanupThread=true
2、将常用fq查询合并,减少结果集求交次数 (略增加内存开销)
3、快速加载solr data到linux cache命令
find ./server/solr/ -type f -exec cat {} \; > /dev/null
4、根据实际调整配置参数
5、自定义缓存