搜索系统13:一个查询从solr到lucene都干了些什么事?

用了solr一段时间后,我想了解下solr是如何包装lucene。因为使用过程中几乎没有遇到直接操作lucene代码的情况,这让我有些迷糊。今天来看看一个solr查询的执行过程,经过debug发现了以下堆栈。


再看堆栈顶的方法里的lucene工具类:


哈,这就是lucene类了。这个时候就可能产生很多疑问了,solr不是分core/collection么,这里怎么没有体现?solr不是有缓存么,这里怎么没有看到缓存?


为了回答这些问题,我们从头来梳理这个查询过程。

1.从web.xml的Filter开始。

我的请求url是localhost:8080/solr_web/core/select?q=*:* 。这个url会匹配到上面的Filter。

2.在SolrDispatchFilter的doFilter方法中生成HttpSolrCall并调用其call方法:

这个call方法调用了一个init方法,这个方法从request取到了core的名称,并且获取这个core单独的handler:


3.执行调用链HttpSolrCall.execute->SolrCore.execute->SearchHandler.handleRequest/handleRequestBody。

这个方法中会遍历几种组件(SearchComponent)进行处理,本文涉及的是QueryComponent,进入它的process方法。

这里面根据参数会有对id,group by 等参数的特殊处理,我们先不关注这些。再进入SolrIndexSearcher.search/getDocListC方法。
缓存就是getDocListC用到的。如下:



这里有个filter的判断,这个filter我查了下并没有设置值的地方,所以正常的都为空。如果没有特殊配置应该都会进来判断一下缓存。


下面重点了解下缓存机制:
a.缓存的key是什么?

从上面代码上看是QueryResultKey对象,这不够具体。我们看看得到缓存的数据的过程,首先是queryResultCache.get(key),进入LRUCache的get方法就会发现这就是一个LinkedHashMap.get方法,那key的值实际上就是QueryResultKey.hashCode的返回值了。它是怎么计算的?从下图可以看出来,他就是全部搜索条件计算出来的一个hashcode。


b.缓存什么时候过期?

看一下LRUCache的init方法,会发现这个秘密。


它就是用了个LinkedHashMap,而LRU的并不是它实现的,是LinkedHashMap实现的。这里介绍一下LRU,它是Least recently used,最近最少使用算法。最近的意思是在队列前的,LinkedHashMap最先加入的元素。最少的意思最少被访问(get)的。下图这个图比形象:


而LinkedHashMap如何实现上面那个图的呢?1就不用说了,就是往队尾加。3也简单就是从队首移除。2是get方法做些处理,看LinkedHashMap源码:

如果accessOrder这个参数为true的时候,就会对链表作一个移动的操作,我就不贴afterNodeAccess的源码了。这正是LRUCache用的方法,见上面的图里的map = new LinkedHashMap(initialSize, 0.75f, true)这第三个参数正是accessOrder。


好了,缓存的分析结束了,知道了这些对我们设置缓存的大小的设置、理解缓存生效时间都有帮助吧。如果查询没有命中缓存,程序就会执行到本文第一张图的第一行方法,这个方法基本就是直接调用lucene的查询方法了。

最后来梳理下整个查询流程:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值