`
blue2048
  • 浏览: 178506 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

solr cache

    博客分类:
  • solr
阅读更多

本文将介绍Solr查询中涉及到的Cache使用及相关的实现。Solr查询的核心类就是SolrIndexSearcher,每个core通常在同一时刻只由当前的SolrIndexSearcher供上层的handler使用(当切换SolrIndexSearcher时可能会有两个同时提供服务),而Solr的各种Cache是依附于SolrIndexSearcher的,SolrIndexSearcher在则Cache生,SolrIndexSearcher亡则Cache被清空close掉。Solr中的应用CachefilterCachequeryResultCachedocumentCache等,这些Cache都是SolrCache的实现类,并且是SolrIndexSearcher的成员变量,各自有着不同的逻辑和使命,下面分别予以介绍和分析。

 1SolrCache接口实现类

     Solr提供了两种SolrCache接口实现类:solr.search.LRUCachesolr.search.FastLRUCacheFastLRUCache1.4版本中引入的,其速度在普遍意义上要比LRUCachefast些。

下面是对SolrCache接口主要方法的注释:

复制代码
public interface SolrCache {
  /**
   * Solr在解析配置文件构造SolrConfig实例时会初始化配置中的各种CacheConfig,
   * 在构造SolrIndexSearcher时通过SolrConfig实例来newInstance SolrCache,
   * 这会调用init方法。参数args就是和具体实现(LRUCache和FastLRUCache)相关的
   * 参数Map,参数persistence是个全局的东西,LRUCache和FastLRUCache用其来统计
   * cache访问情况(因为cache是和SolrIndexSearcher绑定的,所以这种统计就需要个
   * 全局的注入参数),参数regenerator是autowarm时如何重新加载cache,
   * CacheRegenerator接口只有一个被SolrCache warm方法回调的方法:
   * boolean regenerateItem(SolrIndexSearcher newSearcher,
   * SolrCache newCache, SolrCache oldCache, Object oldKey, Object oldVal)
   
*/
  public Object init(Map args, Object persistence, CacheRegenerator regenerator);
  /** :TODO: copy from Map */
  public int size();
  /** :TODO: copy from Map */
  public Object put(Object key, Object value);
  /** :TODO: copy from Map */
  public Object get(Object key);
  /** :TODO: copy from Map */
  public void clear();
  /**
   * 新创建的SolrIndexSearcher autowarm方法,该方法的实现就是遍历已有cache中合适的
   * 范围(因为通常不会把旧cache中的所有项都重新加载一遍),对每一项调用regenerator的
   * regenerateItem方法来对searcher加载新cache项。
   
*/
  void warm(SolrIndexSearcher searcher, SolrCache old) throws IOException;
  /** Frees any non-memory resources */
  public void close();
复制代码

}

1.1solr.search.LRUCache

 LRUCache可配置参数如下:

1sizecache中可保存的最大的项数,默认是1024

2initialSizecache初始化时的大小,默认是1024

3autowarmCount:当切换SolrIndexSearcher时,可以对新生成的SolrIndexSearcherautowarm(预热)处理。autowarmCount表示从旧的SolrIndexSearcher中取多少项来在新的SolrIndexSearcher中被重新生成,如何重新生成由CacheRegenerator实现。在当前的1.4版本的Solr中,这个autowarmCount只能取预热的项数,将来的4.0版本可以指定为已有cache项数的百分比,以便能更好的平衡autowarm的开销及效果。如果不指定该参数,则表示不做autowarm处理。

实现上,LRUCache直接使用LinkedHashMap来缓存数据,由initialSize来限定cache的大小,淘汰策略也是使用LinkedHashMap的内置的LRU方式,读写操作都是对map的全局锁,所以并发性效果方面稍差。

1.2solr.search.FastLRUCache

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

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

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

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

实现上,FastLRUCache内部使用了ConcurrentLRUCache来缓存数据,它是个加了LRU淘汰策略的ConcurrentHashMap,所以其并发性要好很多,这也是多数JavaCache的极典型实现。

2filterCache

filterCache存储了无序的lucene document id集合,该cache3种用途:

1filterCache存储了filter queries(fq”参数)得到的document id集合结果。Solr中的query参数有两种,即qfq。如果fq存在,Solr是先查询fq(因为fq可以多个,所以多个fq查询是个取结果交集的过程),之后将fq结果和q结果取并。在这一过程中,filterCache就是key为单个fq(类型为Query),valuedocument id集合(类型为DocSet)的cache。对于fqrange query来说,filterCache表现出其有价值的一面。

2filterCache还可用于facet查询(http://wiki.apache.org/solr/SolrFacetingOverview),facet查询中各facet的计数是通过对满足query条件的document id集合(可涉及到filterCache)的处理得到的。因为统计各facet计数可能会涉及到所有的doc id,所以filterCache的大小需要能容下索引的文档数。

3)如果solfconfig.xml中配置了<useFilterForSortedQuery/>,那么如果查询有filter(此filter是一需要过滤的DocSet,而不是fq,我未见得它有什么用),则使用filterCache

下面是filterCache的配置示例:

复制代码
    <!-- Internal cache used by SolrIndexSearcher for filters (DocSets),
         unordered sets of *all* documents that match a query.
         When a new searcher is opened, its caches may be prepopulated
         or "autowarmed" using data from caches in the old searcher.
         autowarmCount is the number of items to prepopulate.  For LRUCache,
         the prepopulated items will be the most recently accessed items.
      
-->
    <filterCache
      
class="solr.LRUCache"
      size
="16384"
      initialSize
="4096"
复制代码
autowarmCount="4096"/>

       对于是否使用filterCache及如何配置filterCache大小,需要根据应用特点、统计、效果、经验等各方面来评估。对于使用fqfacet的应用,对filterCache的调优是很有必要的。

3queryResultCache

顾名思义,queryResultCache是对查询结果的缓存(SolrIndexSearcher中的cache缓存的都是document id set),这个结果就是针对查询条件的完全有序的结果。下面是它的配置示例:

复制代码

  <!-- queryResultCache caches results of searches - ordered lists of

        
 document ids (DocList) based on a query, a sort, and the range
         of documents requested.
      
-->
    <queryResultCache
      
class="solr.LRUCache"
      size
="16384"
      initialSize
="4096"
      autowarmCount
="1024"/>
复制代码

缓存的key是个什么结构呢?就是下面的类(keyhashcode就是QueryResultKey的成员变量hc):

复制代码
public QueryResultKey(Query query, List<Query> filters, Sort sort, int nc_flags) {
    this.query = query;
    this.sort = sort;
    this.filters = filters;
    this.nc_flags = nc_flags;
    int h = query.hashCode();
    if (filters != null) h ^= filters.hashCode();
    sfields = (this.sort !=null) ? this.sort.getSort() : defaultSort;
    for (SortField sf : sfields) {
      // mix the bits so that sortFields are position dependent
      
// so that a,b won't hash to the same value as b,a
      h ^= (h << 8) | (h >>> 25);   // reversible hash
      if (sf.getField() != null) h += sf.getField().hashCode();
      h += sf.getType();
      if (sf.getReverse()) h=~h;
      if (sf.getLocale()!=null) h+=sf.getLocale().hashCode();
      if (sf.getFactory()!=null) h+=sf.getFactory().hashCode();
    }
    hc = h;
  }
复制代码

因为查询参数是有startrows的,所以某个QueryResultKey可能命中了cache,但startrows却不在cachedocument id set范围内。当然,document id set是越大命中的概率越大,但这也会很浪费内存,这就需要个参数:queryResultWindowSize来指定document id set的大小。Solr中默认取值为50,可配置,WIKI上的解释很深简单明了:

复制代码
  <!-- An optimization for use with the queryResultCache.  When a search
         is requested, a superset of the requested number of document ids
         are collected.  For example, of a search for a particular query
         requests matching documents 10 through 19, and queryWindowSize is 50,
         then documents 0 through 50 will be collected and cached.  Any further
         requests in that range can be satisfied via the cache.
    
-->
    <queryResultWindowSize>50</queryResultWindowSize>
复制代码

相比filterCache来说,queryResultCache内存使用上要更少一些,但它的效果如何就很难说。就索引数据来说,通常我们只是在索引上存储应用主键id,再从数据库等数据源获取其他需要的字段。这使得查询过程变成,首先通过solr得到document id set,再由Solr得到应用id集合,最后从外部数据源得到完成的查询结果。如果对查询结果正确性没有苛刻的要求,可以在Solr之外独立的缓存完整的查询结果(定时作废),这时queryResultCache就不是很有必要,否则可以考虑使用queryResultCache。当然,如果发现在queryResultCache生命周期内,query重合度很低,也不是很有必要开着它。

4documentCache

又顾名思义,documentCache用来保存<doc_id,document>对的。如果使用documentCache,就尽可能开大些,至少要大过<max_results> * <max_concurrent_queries>,否则因为cache的淘汰,一次请求期间还需要重新获取document一次。也要注意document中存储的字段的多少,避免大量的内存消耗。

下面是documentCache的配置示例:

    <!-- documentCache caches Lucene Document objects (the stored fields for each document).
      
-->
    <documentCache
      
class="solr.LRUCache"
      size
="16384"
      initialSize
="16384"/>

5User/Generic Caches

Solr支持自定义Cache,只需要实现自定义的regenerator即可,下面是配置示例:

复制代码
  <!-- Example of a generic cache.  These caches may be accessed by name
         through SolrIndexSearcher.getCache(),cacheLookup(), and cacheInsert().
         The purpose is to enable easy caching of user/application level data.
         The regenerator argument should be specified as an implementation
         of solr.search.CacheRegenerator if autowarming is desired.
    
-->
    <!--
    <cache name="yourCacheNameHere"
      class="solr.LRUCache"
      size="4096"
      initialSize="2048"
      autowarmCount="4096"
      regenerator="org.foo.bar.YourRegenerator"/>
    
-->
复制代码

6The Lucene FieldCache

lucene中有相对低级别的FieldCacheSolr并不对它做管理,所以,luceneFieldCache还是由luceneIndexSearcher来搞。

7autowarm

上面有提到autowarmautowarm触发的时机有两个,一个是创建第一个Searcher时(firstSearcher),一个是创建个新SearchernewSearcher)来代替当前的Searcher。在Searcher提供请求服务前,Searcher中的各个Cache可以做warm处理,处理的地方通常是SolrCacheinit方法,而不同cachewarm策略也不一样。

1filterCachefilterCache注册了下面的CacheRegenerator,就是由旧的key查询索引得到新值put到新cache中。

复制代码
   solrConfig.filterCacheConfig.setRegenerator(
              new CacheRegenerator() {
                public boolean regenerateItem(SolrIndexSearcher newSearcher, SolrCache newCache, SolrCache oldCache, Object oldKey, Object oldVal) throws IOException {
                  newSearcher.cacheDocSet((Query)oldKey, nullfalse);
                  return true;
                }
              }
      );
复制代码

2queryResultCachequeryResultCacheautowarm不在SolrCacheinit(也就是说,不是去遍历已有的queryResultCache中的query key执行查询),而是通过SolrEventListener接口的void newSearcher(SolrIndexSearcher newSearcher, SolrIndexSearcher currentSearcher)方法,来执行配置中特定的query查询,达到显示的预热lucene FieldCache的效果。

queryResultCache的配置示例如下:

复制代码
       <listener event="newSearcher" class="solr.QuerySenderListener">
      <arr name="queries">
        <!-- seed common sort fields -->
        <lst> <str name="q">anything</str> <str name="sort">name desc price desc populartiy desc</str> </lst>
      </arr>
    </listener>
    <listener event="firstSearcher" class="solr.QuerySenderListener">
      <arr name="queries">
        <!-- seed common sort fields -->
        <lst> <str name="q">anything</str> <str name="sort">name desc, price desc, populartiy desc</str> </lst>
        <!-- seed common facets and filter queries -->
        <lst> <str name="q">anything</str> 
              <str name="facet.field">category</str> 
              <str name="fq">inStock:true</str>
              <str name="fq">price:[0 TO 100]</str>
        </lst>
      </arr>
    </listener>
复制代码

3documentCache:因为新索引的document id和索引文档的对应关系发生变化,所以documentCache没有warm的过程,落得白茫茫一片真干净。

尽管autowarm很好,也要注意autowarm带来的开销,这需要在实际中检验其warm的开销,也要注意Searcher的切换频率,避免因为warm和切换影响Searcher提供正常的查询服务。

 

出自 http://www.cnblogs.com/phinecos/archive/2012/05/24/2517018.html

分享到:
评论

相关推荐

    solr cache部分 中文解释

    自己根据solr官方文档 使用谷歌翻译 对原文档cache 部分进行了中文注释方便阅读

    solr中cache综述

    solr中Cache综述 以及部分优化策略

    SOLR的应用教程

    1.2 Solr的特性 4 1.2.1 Solr使用Lucene并且进行了扩展 4 1.2.2 Schema(模式) 5 1.2.3 查询 5 1.2.4 核心 5 1.2.5 缓存 5 1.2.6 复制 6 1.2.7 管理接口 6 1.3 Solr服务原理 6 1.3.1 索引 6 1.3.2 搜索 7 1.4 源码...

    solr基础知识介绍

    6.2 queryResultCache 18 6.3 documentCache 19 7.solrj wiki 19 7.1 SolrJ/Solr cross-version compatibility 19 7.2 Setting the classpath 20 7.2.1 Maven 20 7.3 HttpSolrServer 21 7.3.1 Changing other ...

    trialverse-search-cache:基于Solr的Trialverse搜索缓存

    Solr搜索jena-es数据集Trialverse在jena-es之上的搜索层的原型实现。 要运行,您需要: jena-es在localhost:8080上运行,最好与一些Trialverse数据集一起运行。 使用solr start -s ./jena-es-solr solr 5.3.0 运行...

    usgin-cache-solr-elastic-

    使用缓存 在数据系统中,数据集作为 OGC 网络特征服务 (WFS) 传送,并由数据提供者的分布式网络提供服务。 这些服务中的每一个都被编入一个(或多个)符合 OGC 的 Web 目录服务 (CSW) 的元数据聚合服务中。...

    biocache-service:发生和映射Web服务

    这些服务记录在这里版本号当前有两个受支持的版本: 1.9.x-SOLR 4和Cassandra1.2.x。 请参阅1.9.x分支。 2.x-具有SOLR Cloud支持和Cassandra 3.x的SOLR 7。 参见master分支。开发设置参见Wiki: : 整合测试使用...

    Django By Example 无水印pdf 0分

    Use Django with other technologies such as Redis, Celery, Solr and Memcached Develop pluggable Django applications Create advanced features, optimize your code and use the cache framework Add ...

    canal-php 监控数据库变更

    Canal 是mysql数据库binlog的增量订阅&消费组件。...2.根据数据库的变更实时更新搜索引擎,比如电商场景下商品信息发生变更,实时同步到商品搜索引擎 Elasticsearch、solr等 3.根据数据库的变更实时更新缓

    Play Framework Cookbook(PlayFramework )(September 4, 2011)

    Write own render methods to return custom formats for creating custom PDFs or RSS and ATOM feed responsesUnderstand internal caching and implement your own cache in just a few lines of code ...

    spring boot 实践学习案例,与其它组件整合

    - Spring Boot 缓存,包括redis、ehcache、spring-cache、memcached、使用redis实现session共享 等。 - springboot-templates - Spring Boot 模板,包括thymeleaf、freemarker、jsp、表单校验 等。 - ...

    django2 by examples

    Use Django with other technologies such as Redis, Celery and Solr. Develop pluggable Django applications Create advanced features, optimize your code and use the cache framework Add ...

    javaEngine

    1) 路灯(1) 迭代器(1) 算法分析(1) apache(1) 容易被下载(1) 多个关键字请(1) c++(1) solr(1) 0(1) 缓存(1) 缓冲(1) 书记袁(1) 击右侧我的(1) java笑脸(1)

    springboot学习思维笔记.xmind

    spring-boot-starter-data-solr spring-boot-starter-freemarker spring-boot-starter-groovy-templates spring-boot-starter-hateoas spring-boot-starter-hornetq spring-boot-...

    javaweb项目常用jar包

    spring-cache-3.3.0.jar spring-context-4.1.6.RELEASE.jar spring-context-support-4.1.6.RELEASE.jar spring-core-4.1.6.RELEASE.jar spring-data-commons-1.10.0.RELEASE.jar spring-data-mongodb-1.7.0....

    spring-boot-reference.pdf

    31.1. Supported Cache Providers 31.1.1. Generic 31.1.2. JCache (JSR-107) 31.1.3. EhCache 2.x 31.1.4. Hazelcast 31.1.5. Infinispan 31.1.6. Couchbase 31.1.7. Redis 31.1.8. Caffeine 31.1.9. Simple 31.1....

    spring-boot-demo:Spring Boot和Spring Cloud和Spring Security演示案例(Spring学习示例实战项目)

    SpringCache的 定时器 搜索ES 搜索 项目工程: 三, MVC篇 过滤器 项目工程: 基本使用姿势: filter优先级: 拦截器 获取/发布/放置/删除等http方法支持 参数绑定(get / post参数解析,自定义参数解析器)

    GeoParser:从任何文件提取并可视化位置

    docker build -t nasajplmemex/geo-parser --no-cache -f Dockerfile . docker-compose up -d 在浏览器上访问http://localhost:8000 尝试一下以帮助对抗COVID! GeoParser已更新,具有易于使用的新Docker安装,...

    java开源包1

    Smart Cache 是一个采用 Java 开发的 HTTP/1.1代理服务器,也可以用来作为Web的缓存系统。 高性能的JSON处理 Jackson Jackson 是一个 Java 用来处理 JSON 格式数据的类库,性能非常好。 哈希计算工具 java-hash ...

    java开源包11

    Smart Cache 是一个采用 Java 开发的 HTTP/1.1代理服务器,也可以用来作为Web的缓存系统。 高性能的JSON处理 Jackson Jackson 是一个 Java 用来处理 JSON 格式数据的类库,性能非常好。 哈希计算工具 java-hash ...

Global site tag (gtag.js) - Google Analytics