`
粟谷_sugu
  • 浏览: 25492 次
社区版块
存档分类
最新评论

解决solr缓存造成的query查询问题

    博客分类:
  • solr
阅读更多
背景
目前在公司,实现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
0
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics