您的位置:首页 > 其它

solr分布式搜索源码分析

2013-08-16 09:59 253 查看
基于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);

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: