Solr复制bug一例:Unable to move index file from tempfile to indexfile

星期三, 十一月 24th, 2010

22日下午3时多,收到搜索系统的报警邮件,错误日志如下:
[2010-11-22 15:16:14][ERROR][pool-6-thread-1][SnapPuller.java(650)]Unable to move index file from: /indexpath/index.20101122031500/_21.frq to: /indexpath/index.20101122031000/_21.frq
SnapPuller是Solr复制用到的一个类,我对它做了一些修改,所以把它挪到我的代码里了。报错的代码片断如下:

httpclient的并发连接问题

星期六, 十一月 20th, 2010

昨天的搜索系统又出状况了,几个库同时重建索引变得死慢。经过一个上午的复现分析,确定问题出现httpclient的使用上。搜索系统在重建索引时,是并发多个线程(默认是8个)不停的从PHP客户端取数据(当然,从另一个角度来说,搜索系统是客户端,PHP端是服务端),取回后放到一个队列里由单独的一个线程更新索引。在测试环境复现发现,对于一个请求,PHP端打印耗时是1-2秒,但搜索端打印在4-6秒。这种耗时差别也就两种可能性,一个是PHP端返回到搜索端接受完耗时太长,另一个就是搜索端在真正发给PHP端数据前等待了很久。因为有了之前的jetty7的困顿,起初我怀疑是传输数据的问题。因为请求数据的代码部分我只是简单的使用了httpclient,所以只能从httpclient着手分析。我想到把PHP端和搜索端的请求起始和结束时间都打出来对照一下,不过在这样做之前我把搜索端的并发请求线程数调到了1,看下单线程情况下效果如何,结果惊奇地发现PHP端和搜索端的耗时相近。所以,可以确定,是httpclient的并发连接处理上可能存在问题。

solr拾遗:引用计数

星期六, 十一月 13th, 2010

据我不完全统计,solr代码中使用引用计数的用途有两种:一个是引用资源,一个是引用对象。技术上来说引用计数的使用没多少可大说的,不过如果没有正确的close获得的资源和对象,泄漏的bug就出现了。

solr拾遗:CopyField

星期六, 十月 30th, 2010

solr的index schema中,除了支持基本数值类型的field,还支持一些特别的field,比如较常用的CopyField。以下面的schema配置片断为例:

<schema name="eshequn.post.db_post.0" version="1.1"
xmlns:xi="http://www.w3.org/2001/XInclude">
<fields>
<!– for title –>
<field name="t" type="text" indexed="true" stored="false" />
<!– for abstract –>
<field name="a" type="text" [...]

solr filter query的误用

星期五, 十月 22nd, 2010

在我整理solr SolrIndexSearcher性能问题分析的时候,我就在想,我是不是误用了SolrIndexSearcher,才出现我所以为的性能问题。当我想到其实现特点,我恍惚确定确实是这样的,根源就是我误用 filter query。上篇文章暂且放下,这篇做个补充。如我上文所述,fq=fid:1这个条件匹配的文档数会很多,不过,如果开启了filter cache,那么只会在第一次调用时慢些,后续的调用都会命中cache而提升速度,而通过query预热是可以解决初次调用的低速问题。所以,如果要使用filter query,就要开启filter cache,并确保filter cache能容纳所有的filter query。这也需要对应用的查询特点做好分析。以fq=atm:[int_time1 TO int_time2]为例,我之前是将它放到filter query中,不过因为每次查询的int_time1和int_time2都几乎不相同,使得总不能命中filter cache,严重影响了查询性能。另一方面,我在做压力测试时也发现,当filter query结果充满了filter cache,最终使得程序内存耗尽。

solr SolrIndexSearcher性能问题分析

星期四, 十月 21st, 2010

基于solr的新搜索系统已经使用了有段时间,不过之前上的几个库都很小,也没发现什么性能问题。最近上了thread和post库后,性能问题显现出来。这段时间解决的性能问题有好几个,本文只着重于SolrIndexSearcher的search问题。thread库索引大小有400M多,记录数有400多万,原来的基于lucene的系统的查询处理耗时一般在10-30ms,而同样的请求,新系统耗时在50-100ms。而post库索引大小有 6G多,记录数有3000多万,旧系统的查询处理时间一般在30-80ms,而新系统往往需要400-800ms,性能差距还是很明显的。
因为SolrIndexSearcher是基于lucene的IndexSearcher,想必应该是青出于蓝胜于蓝,并且其wiki上给出的性能数据也很不错,所以当我把新系统做完后并没有去细致的测试其性能。但现在系统的性能相比之下确实有些差,并且因为要做多个库的整合搜索,就要避免像thread 这样耗时长的库就成为短板。总之,问题需要定位和解决。

[Solr实践]自定义SolrEventListener实现searcher的autowarm策略

星期天, 九月 5th, 2010

Solr的searcher autowarm(预热)有两个时机,一个是系统启动时(firstSearcher),一个是使用新的searcher替换旧的searcher时(newSearcher)。Solr支持在solrconfig.xml中对SolrCore配置SolrEventListener来实现自定义的autowarm。通常来说,Solr提供的默认实现QuerySenderListener就够用了。在我的需求中,希望solrconfig.xml中配置的SolrEventListener是针对多个SolrCore的,这要是因为我的多个SolrCore共用了一个solrconfig.xml配置。就配置autowarm的查询query来说,简单的就是配置一个常见的query,但如果系统有排序查询(sort),可以配置适宜的sort条件以预热lucene的fieldCache。下面是我自定义的SolrEventListener,效果是,如果SolrCore没有配置query,就使用default的,否则使用自己的。

Solr之困

星期天, 八月 22nd, 2010

重写公司的站内搜索。经过前期一段时间对lucene和solr的熟悉,最后决定使用Solr作为新系统的基础框架。现在已经是第一阶段开发的后期,核心代码行数有11000+(不包含admin及client等)。现已实现的功能要比已有系统要丰富些,但综合比较两个系统总的代码量,其实新系统并不多得太多。新系统使用Solr代替了已有系统实现的部分功能,这减少了新系统的代码量,同是新系统实现了已有系统不具有的功能,也增加了一些代码量。开发的这段时间,因为新系统中很多代码是独立于Solr的,所以和Solr的交互也是时断时续,以使得即便到了开发后期我还能发现Solr实现的一些细节带给我的困扰。

[Solr源码分析]LRUCache和FastLRUCache实现分析

星期一, 八月 9th, 2010

在 [Solr 实践]Solr Cache使用介绍及分析 一文我有对Solr的LRUCache和FastLRUCache做了一些介绍,本文在此基础对其实现做些补充。
1、LRUCache的实现分析
在分析LRUCache前先对LinkedHashMap做些介绍。LinkedHashMap继承于HashMap,它使用了一个双向链表来存储Map中的Entry顺序关系,这种顺序有两种,一种是LRU顺序,一种是插入顺序,这可以由其构造函数public LinkedHashMap(int initialCapacity,float loadFactor, boolean accessOrder)指定。所以,对于get、put、remove等操作,LinkedHashMap除了要做HashMap做的事情,还做些调整Entry顺序链表的工作。
以get操作为例,如果是LRU顺序(accessOrder为true),Entry的recordAccess方法就调整get到的Entry到链表的头部去:

public V get(Object key) {
Entry<K,V> e = (Entry<K,V>)getEntry(key);
if (e [...]

[Solr实践]Solr Cache使用介绍及分析

星期天, 八月 1st, 2010

本文将介绍Solr查询中涉及到的Cache使用及相关的实现。Solr查询的核心类就是SolrIndexSearcher,每个core通常在同一时刻只由当前的SolrIndexSearcher供上层的handler使用(当切换SolrIndexSearcher时可能会有两个同时提供服务),而Solr的各种Cache是依附于SolrIndexSearcher的,SolrIndexSearcher在则Cache生,SolrIndexSearcher亡则Cache被清空close掉。Solr中的应用Cache有filterCache、queryResultCache、documentCache等,这些Cache都是SolrCache的实现类,并且是SolrIndexSearcher的成员变量,各自有着不同的逻辑和使命,下面分别予以介绍和分析。

[Solr源码分析]Solr复制类ReplicationHandler实现简要分析

星期天, 七月 25th, 2010

在上一文《solr ReplicationHandler使用介绍》的基础上,本文接着对solr的ReplicationHandler实现细节做些分析,这个分析原则上没有摘取大段代码,窃以为摘了代码后未见得有很好的阐述效果,但不摘取后窃又发现,阐述的效果依旧不好。归结起来,还是窃的表达不够深入浅出所致。闲言少叙,直接上内容。

[Solr实践]Solr复制类ReplicationHandler使用介绍

星期六, 七月 24th, 2010

solr1.4中引入ReplicationHandler代替外部脚本来复制索引数据,ReplicationHandler使得复制索引数据更自动化。对于使用者来说,只要简单的配置好,就可以一劳永逸的享受solr的复制功能了。下面介绍其使用相关内容。

分享Sify.com的架构经验

星期六, 五月 15th, 2010

今天分享的网站架构来自于Sify.com Architecture – A Portal at 3900 Requests Per Second(该标题有标题党嫌疑),对英文熟稔并不屑于我的中文简述的可以跳过该文。Sify.com是印度的一家portal网站,应该是信息集成类网站。它给出的月 pv是1.5亿次,每秒请求数是3900次(应该是针对所有服务的页面请求,包括异步的,并且是高峰的,否则就和pv对不上了)。按规模来说,算是个中等规模的网站,不过它的架构却是很值得说道的。