solr4.0 的缓存策略

2019-03-27 01:00|来源: 网路

solr的缓存策略分3种

 

LRUCache:使用LinkedHashMap来保存缓存,覆盖了removeEldestEntry方法,并提供了预热方法:

  public void warm(SolrIndexSearcher searcher, SolrCache<K,V> old) {
    if (regenerator==null) return;
    long warmingStartTime = System.currentTimeMillis();
    LRUCache<K,V> other = (LRUCache<K,V>)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<Map.Entry<K, V>> 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<skip; i++) iter.next(); 导入 for (int i=0; i<sz; i++) { Map.Entry<K,V> 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<keys.length; i++) { try {
  // 这一步是最终预热的过程
boolean continueRegen = regenerator.regenerateItem(searcher, this, old, keys[i], vals[i]); if (!continueRegen) break; } catch (Throwable e) { SolrException.log(log,"Error during auto-warming of key:" + keys[i], e); } } } warmupTime = System.currentTimeMillis() - warmingStartTime; }

 

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 

Solr1.4引入FastLRUCache作为另一种可选的实现。FastLRUCache放弃了LinkedHashMap,而是使用现在很多Java Cache实现中使用的ConcurrentHashMap。但ConcurrentHashMap只提供了高性能的并发存取支持,并没有提供对淘汰数据的支持,所以FastLRUCache主要需要做的就是这件事情。FastLRUCache的存取操作都在ConcurrentLRUCache中实现,所以我们直接过渡到ConcurrentLRUCache的实现。

 

 

 

LFUCache


转自:http://www.cnblogs.com/zhang-mohan/archive/2013/01/21/2869619

相关问答

更多
  • 1. commit 有返回值的 UpdateResponse updateResponse = solrServer.commit();int status = updateResponse.getStatus()这里的 status 可以拿到操作执行的状态 ,0表示 成功 if (status != 0) { log.error("Some horrible error has occurred, status is:" + status); } 2. try{ UpdateResponse addBea ...
  • 最近我一直在使用DotNetNuke来开发Web应用程序,并且每次实施缓存解决方案时都会考虑许多事情。 所有用户都需要查看缓存的内容吗? 每一部分内容的变化频率如何? 我可以缓存整个页面吗? 我是否需要手动清除缓存? 我可以为整个站点使用单个缓存机制,还是需要多个解决方案? 如果信息过时,会产生什么影响? I have been working with DotNetNuke most recently for web applications and there are a number of thing ...
  • @ nikano的答案是正确的,如果你想在将URLSession用作Siesta的底层网络库时控制它的缓存行为。 一般来说,Siesta让底层网络做到了。 即使与Siesta一起使用,对URLSession有效的选项URLSession保持不变。 Siesta 本身是一个可观察的内存缓存。 它的核心设计特征之一是,它可以让您对所看到,缓存或新鲜的数据进行细粒度控制 - 这一点至关重要。 你可以使用两者。 如果你想在内存中看到本地缓存的数据,你的“仅限本地”,只需要一个资源: resource.latestD ...
  • 除了其他原因,为什么否是一个答案,也是变化的粒度。 Lucene(底层库)以只读形式存储数据。 Solr在其上添加了可更新的文档,但是使它们可见仍然是一个繁重的操作。 Solr的最新版本通过软提交使其变得更容易和更快,但是使可见变化的代价仍然是非常重要的。 因此,它实际上没有针对更新/缓存单个值进行优化。 数据结构针对多文档更新进行了优化,然后通过缓存超过该临时只读状态进行快速搜索。 In additions to other reasons why No would be an answer, is al ...
  • 有两个主要选项:1。使用纯默认的http缓存(默认的volley实现或者volley使用的任何hhtp堆栈之一)2。使用您自己的自定义缓存,您可以在其中准确定义缓存的方式和内容 我将详细介绍选项1.因为它似乎你使用了这个。 当您缓存响应时,通常不需要外部信息何时更新它们,因为信息包含在返回的缓存标头中。 所以响应(例如一篇文章)可以是:1)缓存有效缓存 - 在这种情况下没有请求进入网络层2)缓存的女巫需要重新验证 - 在这种情况下你可能会收到新版本的没有正文的响应或304响应,这意味着当前缓存有效并且仍然可 ...
  • 我假设你在其他地方过滤这个列表......否则这就是一个列表。 在点击数据库之前点击新的,更精简的静态缓存的最简单方法是通过单个方法传递所有请求: public yourClass GetDesiredObject(string lkupValue) { if (yourCachedHashtable.ContainsKey(lkupValue)) { return yourCachedHashtable[lkupValue] } else { //Hit the d ...
  • 我能够确定我的返回函数出了什么问题:我没有在结果中正确循环。 最好的方法是使用map函数迭代它们。 $("#Keyword").autocomplete({ minLength: 3, source: function(request, response) { $query = "http://127.0.0.1:8080/solr/terms/?jsoncallback=?&terms=true&terms.prefix=" + $("#Keyword").val(); ...
  • 使用solr 4.0, BaseTokenFilterFactory现在是org.apache.lucene.analysis.util.TokenFilterFactory ,所以你可以检查一下 。 With solr 4.0 the BaseTokenFilterFactory is now org.apache.lucene.analysis.util.TokenFilterFactory, so you can check on this.
  • AFNetworking具有图像内存缓存功能。 如果你有100张图片可能适合你,可能不适合你。 您还应该在这里阅读有关NSURLCache的信息 - http://nshipster.com/nsurlcache/ 。 如果你使用NSURLCache,你不必考虑缓存 - 当你开始下载已经缓存的东西时,系统只会给你下载文件。 更新:下载数据的时间到期由服务器设置响应。 但您可以通过NSURLConnectionDelegate方法编辑或忽略它。 例: - (NSCachedURLResponse *)conn ...
  • 除了新功能之外,Solr 3.6和Solr 4.0之间是否有任何重大差异? 我发现这个问题很奇怪,至少可以说。 错误修复和新功能是发布的全部内容! 您可以在此处查看 Solr版本的完整更新日志。 不要忘记Solr和Lucene是一致发布的,所以你还需要在两个项目中寻找相关的变化。 我可以安全地使用我在Solr 4.0中的现有查询(在Solr 3.6中工作的查询)吗? 查询应该没问题,但索引 - 可能不是。 引用另一篇SO帖子中的 javanna: 索引格式已更改,但Solr将负责升级索引。 一旦用旧索引启动 ...