solr的缓存策略分3种
LRUCache:使用LinkedHashMap来保存缓存,覆盖了removeEldestEntry方法,并提供了预热方法:
public void warm(SolrIndexSearcher searcher, SolrCacheold) { if (regenerator==null) return; long warmingStartTime = System.currentTimeMillis(); LRUCache other = (LRUCache )old; // warm entries if (isAutowarmingOn()) { Object[] keys,vals = null; // Don't do the autowarming in the synchronized block, just pull out the keys and values. // 先获取旧缓存的锁 再导入 synchronized (other.map) { int sz = autowarm.getWarmCount(other.map.size()); keys = new Object[sz]; vals = new Object[sz]; Iterator > iter = other.map.entrySet().iterator(); // iteration goes from oldest (least recently used) to most recently used, // so we need to skip over the oldest entries. // 最久的跳过 int skip = other.map.size() - sz; for (int i=0; i entry = iter.next(); keys[i]=entry.getKey(); vals[i]=entry.getValue(); } } // autowarm from the oldest to the newest entries so that the ordering will be // correct in the new cache. for (int i=0; i
org.apache.solr.search.SolrIndexSearcher.initRegenerators(this); 这行代码决定了solr的每种缓存的加载的具体方式 一共3种 在solrconfig的构造函数里执行
具体的函数:
public static void initRegenerators(SolrConfig solrConfig) { if (solrConfig.fieldValueCacheConfig != null && solrConfig.fieldValueCacheConfig.getRegenerator() == null) { solrConfig.fieldValueCacheConfig.setRegenerator( new CacheRegenerator() { public boolean regenerateItem(SolrIndexSearcher newSearcher, SolrCache newCache, SolrCache oldCache, Object oldKey, Object oldVal) throws IOException { if (oldVal instanceof UnInvertedField) { UnInvertedField.getUnInvertedField((String)oldKey, newSearcher); } return true; } } ); } if (solrConfig.filterCacheConfig != null && solrConfig.filterCacheConfig.getRegenerator() == null) { solrConfig.filterCacheConfig.setRegenerator( new CacheRegenerator() { public boolean regenerateItem(SolrIndexSearcher newSearcher, SolrCache newCache, SolrCache oldCache, Object oldKey, Object oldVal) throws IOException { newSearcher.cacheDocSet((Query)oldKey, null, false); return true; } } ); } if (solrConfig.queryResultCacheConfig != null && solrConfig.queryResultCacheConfig.getRegenerator() == null) { final int queryResultWindowSize = solrConfig.queryResultWindowSize; solrConfig.queryResultCacheConfig.setRegenerator( new CacheRegenerator() { public boolean regenerateItem(SolrIndexSearcher newSearcher, SolrCache newCache, SolrCache oldCache, Object oldKey, Object oldVal) throws IOException { QueryResultKey key = (QueryResultKey)oldKey; int nDocs=1; // request 1 doc and let caching round up to the next window size... // unless the window size is <=1, in which case we will pick // the minimum of the number of documents requested last time and // a reasonable number such as 40. // TODO: make more configurable later... if (queryResultWindowSize<=1) { DocList oldList = (DocList)oldVal; int oldnDocs = oldList.offset() + oldList.size(); // 40 has factors of 2,4,5,10,20 nDocs = Math.min(oldnDocs,40); } int flags=NO_CHECK_QCACHE | key.nc_flags; QueryCommand qc = new QueryCommand(); qc.setQuery(key.query) .setFilterList(key.filters) .setSort(key.sort) .setLen(nDocs) .setSupersetMaxDoc(nDocs) .setFlags(flags); QueryResult qr = new QueryResult(); newSearcher.getDocListC(qr,qc); return true; } } ); } }
先看一下:fieldValueCacheConfig 这个配的是facet分组查询时用的缓存
solrconfig里是默认注释掉的
在SolrConfig类里的代码:
public SolrConfig(SolrResourceLoader loader, String name, InputSource is)
throws ParserConfigurationException, IOException, SAXException 方法里初始化CacheConfig conf = CacheConfig.getConfig(this, "query/fieldValueCache");
if (conf == null) { Map<String,String> args = new HashMap<String,String>(); args.put("name","fieldValueCache"); args.put("size","10000"); args.put("initialSize","10"); args.put("showItems","-1"); conf = new CacheConfig(FastLRUCache.class, args, null); }
看网上的资料说:
FacetComponent 在根据某个field的词时,会用到fieldValueCache,key是facet.field的值,value是UnInvertedField,
UnInvertedField这个类主要负责完成把field域每个词Term,以及词Term在所有文档field域的频率,即出现的次数。保存在一个数组中,创建的UnInvertedField保存在fieldValueCache缓存中,得到UnInvertedField后,调用UnInvertedField的getCounts方法,跟查询到的document ID 做交集,如果不是查询结果的document ID,,则该Field的词的个数为0,除此之外,还对field出现的词做一个排序,solr的FacetComponet有两种排序选择,分别是count和index,count是按每个词出现的次数,index是按词的字典顺序。如果查询参数不指定facet.sort,solr默认是按count排序。UnInvertedField的具体以后再说,接着说加载缓存的过程
documentCache和queryResultCache是用的LRUCache
documentCache 是在每次调用
public StoredDocument doc(int i, Set<String> fields) throws IOException 方法时自动追加缓存
if (documentCache != null) { documentCache.put(i, d); }return d;
未完 待续 下一篇主要介绍预热的过程
一种是FastLRUCache
LFUCache