solr分布式搜索源码分析

基于solr4.4   

   分布式搜索的主控逻辑是在SearchHandler.handleRequestBody方法中实现的,参见distributed request分支
分布式搜索过程是分阶段stage的,stage的控制在每个componnet的distributedProcess方法中,每个stage的请求输出都会封装在outgoing.add(sreq)中。
component针对每个stage做相应的参数的设置和处理,并输出到outgoing中,在while循环中检测到outgoing有值,则代表需要对该请求,进行分布式的调用;
分布式调用会针对当前的stage提交每个shard的查询,并异步收集所有shard的返回结果。
 每个stage计算完成后,对结果进行处理
 for(SearchComponent c : components) {
              c.handleResponses(rb, srsp.getShardRequest());
            }

所有的stage都完成后,调用component.finishStage进行后续的处理
   for(SearchComponent c : components) {
          c.finishStage(rb);
        }


stage主要分两个stage,为makeQuery和getFileds
      makeQuery,给url带上查询参数fl=id,score根据情况是否会带,我们知道fl是代表只返回那些field,Solr会取schema配置文件的uniquerField,所以这次请求就只返回id的值。得到id值后,QueryComponent会合并id,如果不同的shard有相同的id,则会只取一个
      getFileds,通过QueryComponent来封装请求参数,其中最关键的是封装ids参数,即根据上面请求得到的ids参数把他作为值放到url里,再一次发请求根据id来取对应的field
其实在这两个阶段之前,还有一个阶段是STAGE_PARSE_QUERY,在这个阶段可以计算分布式的idf,不过目前solr没有实现,而是默认每个shard只计算自己的idf,并不会计算全局的idf,在数据量较大的情况下,基于Shard层次的TF-IDF不会有太大的偏差,但是如果分布式索引非常不均衡,可能就要重视相关度的计算问题.

      makeQuery stage完成后,对所有shards返回的docs进行mergeIds操作,mergeIds实现中会根据分页把doc放到优先级队列中,根据sort和score进行比较排序,获取当前页面的doc list,这里存在一个问题,优先级队列的size是start+rows,只返回rows大小的给客户端,不过需要对top的start+rows数量的doc进行排序,的对于翻页比较多的情况,代理节点内存的开销和排序计算的CPU开销都会比较大

比如
QueryComponent,
  private void handleRegularResponses(ResponseBuilder rb, ShardRequest sreq) {
    if ((sreq.purpose & ShardRequest.PURPOSE_GET_TOP_IDS) != 0) {
      mergeIds(rb, sreq);
    }

    if ((sreq.purpose & ShardRequest.PURPOSE_GET_FIELDS) != 0) {
      returnFields(rb, sreq);
    }
  }

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值