欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

解决solr缓存造成的query查询问题 博客分类: solr solrcacheidea 

程序员文章站 2024-03-18 19:08:10
...
背景
目前在公司,实现solr的一个菜名推荐模块的时候,遇到了一个困扰了好几天的问题,就是当实现了模块的逻辑代码并确认功能实现后,在部署测试后发现了一个bug,就是多次查询结果均重复第一次查询的结果。
问题排查
首先想到是不是之后的几次查询并没有真正调用到实现的逻辑,所以在本地IDEA中远程调试服务器上代码,发现当在solr中查询时,确实进入到逻辑代码中打得断点,而且确实传递了不同的query参数到方法中,只是返回的结果依旧不符合预期,只是重复第一次的结果。
再次考虑到是不是solr的某些缓存机制,将多条查询结果识别为了同一条,并直接返回了缓存中的结果。想到这个结果后,我开始了漫长的单步调试过程,希望定位到可能有问题的代码中,并同时在查找关于solr缓存的相关内容。
最后在solr的conf文件中,定位到了相关缓存代码
<query>
    <maxBooleanClauses>1024</maxBooleanClauses>

    <filterCache class="solr.FastLRUCache"
                 size="512"
                 initialSize="512"
                 autowarmCount="0"/>

    <!-- 加上这段,会有多次查询结果相同的问题-->
    <queryResultCache class="solr.LRUCache"
                     size="512"
                     initialSize="512"
                     autowarmCount="0"/>
     
    <documentCache class="solr.LRUCache"
                   size="512"
                   initialSize="512"
                   autowarmCount="0"/>
    
    <cache name="perSegFilter"
      class="solr.search.LRUCache"
      size="10"
      initialSize="0"
      autowarmCount="10"
      regenerator="solr.NoOpRegenerator" />

测试时发现当删掉中间标注的一段时,查询正常,所以确认是由于queryResultCache缓存将不同的query判断为同一个key,所以之后的查询均直接调用第一次缓存的结果。
发现这个结果后,查看queryResultCache的key是由什么确定的。
package org.apache.solr.search;
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();
        Query filt;
        if(filters != null) {
            for(Iterator var6 = filters.iterator(); var6.hasNext(); h += filt.hashCode()) {
                filt = (Query)var6.next();
            }
        }

        this.sfields = this.sort != null?this.sort.getSort():defaultSort;
        SortField[] var10 = this.sfields;
        int var11 = var10.length;

        for(int var8 = 0; var8 < var11; ++var8) {
            SortField sf = var10[var8];
            h = h * 29 + sf.hashCode();
        }

        this.hc = h;  
    }

以上就是queryResultCache的key的定义类,其中key的hashcode就是hc属性。由定义可知,
int h = query.hashCode();
this.hc = h;
,经过单步调试,发现不同的query查询后,在此处得到的hc都是一样的,所以精确定位了问题出在自定义的query的hashcode生成中。
FreqQuery entends bitQuery extends Query
在超类Query中,定义方法
@Override
  public int hashCode() {
    return getClass().hashCode();
  }

继承的子类均没有覆写hashcode()方法,所以每个query的hashcode均相同。
定位问题后,修改方法也就很简单了,在FreqQuery中覆写此方法,注意做到各query的区分,同时也要保证相同query能命中缓存,此处我采用query的hashcode作为query的hashcode。修改完成后,提交代码,部署应用,发现结果和预期相同了。


远程调试的教程
https://www.cnblogs.com/wy2325/p/5600232.html
浅谈solr缓存
http://www.cnblogs.com/phinecos/archive/2012/05/24/2517018.html
相关标签: solr cache idea