MDA/MDD/TDD/DDD/DDDDDDD
posts - 536, comments - 111, trackbacks - 0, articles - 0
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

lucene实时搜索相关

Posted on 2010-11-22 17:18 leekiang 阅读(1517) 评论(0)  编辑  收藏 所属分类: lucene
在做一个网站站内搜索中,使用lucene实现实时搜索时,我遇到了一对矛盾:在使用一个IndexSearcher单例时,搜索的效率极高,但是在 indexSearcher实例新建后新增的索引,这个单例是不可见的,除非我定时的去触发将这个IndexSearcher重新建一次,否则就不能搜索出最新的信息。假如我每来一个 request,就新建一个IndexSearcher实例,则可以搜索出最新的信息,但是,效率非常低。不知道大家有什么好的策略或插件,提出来讨论讨论。(我现在的策略是定时的reopen下insexSearcher)

可以使用这样的策略:
使用一个独立的线程去维护这个IndexSearcher,当索引有更新时,记录下索引已更新;当有request时,先去检验一下索引是否有更新,有则reopen后再查,无则直接查。

最简单的方法,用timer定时生成下indexSearcher,全文引擎有略微的延时也是可以接受的。

用2.3的包,有一个reopen()的方法,只会加载变化的索引片段。
每次索引更新之后,对于当前正在使用的IndexReader来说不是可见的,必须重新open一次Index,才能保证能够搜索到新加入的 document,2.3相当于做了一次增量的open。
每一次reopen前可以先判断一下是不是当前的索引文件,主要看有没有更新,
如果有更新,用reopen()方法打开,看它文档上说明是只加载更新了的索引文件,这样就不用全部重新打开了,时间主要耗在这里,如果判断结果是没有更新则直接返回那个实例就行了
IndexReader.reopen一直是没有实现的?

比如在你加了索引之后新生成一个searcher把那个单例给替换了 ,但是,当几十的并发增量索引过来的时候,就不能这么触发了,我现在只是弄了个timer,定时30秒钟来换个IndexSearcher实例。

the singleton of IndexSearcher will be more efficient.
see http://wiki.apache.org/lucene-java/ImproveSearchingSpeed

由于前一章所述的Lucene的事务性,使得Lucene可以增量的添加一个段,我们知道,倒排索引是有一定的格式的,而这个格式一旦写入是非常难以改变的,那么如何能够增量建索引呢?Lucene使用段这个概念解决了这个问题,对于每个已经生成的段,其倒排索引结构不会再改变,而增量添加的文档添加到新的段中,段之间在一定的时刻进行合并,从而形成新的倒排索引结构。
然而也正因为Lucene的事务性,使得Lucene的索引不够实时,如果想Lucene实时,则必须新添加的文档后IndexWriter需要commit,在搜索的时候IndexReader需要重新的打开,然而当索引在硬盘上的时候,尤其是索引非常大的时候,IndexWriter的commit操作和IndexReader的open操作都是非常慢的,根本达不到实时性的需要。
好在Lucene提供了RAMDirectory,也即内存中的索引,能够很快的commit和open,然而又存在如果索引很大,内存中不能够放下的问题。

所以要构建实时的索引,就需要内存中的索引RAMDirectory和硬盘上的索引 FSDirectory相互配合来解决问题。

Zoie 是linkedin支持的基于Lucene开源实时搜索引擎项目

  Solr  ( http://lucene.apache.org/solr/  )
说明:基于 Lucene 的企业级搜索的开箱即用的解决方案
优点:比较成熟的解决方案,也有很多的成功案例。Lucene 子项目,实现了大部分常见的搜索功能需求,包括 facet 搜索(搜索结果分类过滤)等。
缺点:可定制性比 Lucene 要差,一些不常见的需求,定制的难度比直接在 Lucene 上做要大的多。性能上,由于 Solr 的建索引和搜索是同一个进程,耦合度比较高,对于性能调优有一定的影响。

  直接使用 Lucene  ( http://lucene.apache.org  )
说明:Lucene 是一个 JAVA 搜索类库,它本身并不是一个完整的解决方案,需要额外的开发工作
优点:成熟的解决方案,有很多的成功案例。apache顶级项目,正在持续快速的进步。庞大而活跃的开发社区,大量的开发人员。它只是一个类库,有足够的定制和优化空间:经过简单定制,就可以满足绝大部分常见的需求;经过优化,可以支持10亿+ 量级的搜索。
缺点:需要额外的开发工作。所有的扩展,分布式,可靠性等都需要自己实现;非实时,从建索引到可以搜索中间有一个时间延迟,而当前的“近实时” (Lucene Near Real Time search)搜索方案的可扩展性有待进一步完善

2.9新版本引入了IndexWriter.getReader()方法,它可用于搜索目前完整的索引,包括当前IndexWriter会话中还没有提交的改变,这带来了接近于实时搜索的能力。此外,你还可以调用IndexWriter.setMergedSegmentWarmer()方法进行“预热”,这样那些片断便可以立即投入使用了。

2.9版本之前的版本,都是基于文本搜索的,因为对于很多数字的处理方式就很头疼,例如在我们项目中遇到的很多问题都是由于把数字当作了文本处理出现的 BUG:1、搜索价格的5,把包含.5的也搜索出来了;2、排序(降序)时,把800排到5000前面;……这些都是由于Lucene把所有的都作为文本处理的方式造成的问题。Lucene 2.9以后已经自带对数字的处理方式。Field和Query类会采取合适的精度进行索引和搜索,这样大大降低了需要搜索的关键字数量,使查询的响应能力得以显著提高。

我们web应用是好几台机器,而索引也有好几种,如果用lucene的话,定时更新不能保证所有服务器同步。如果用mount方式,lucen也有问题, 所以想用solr统一管理所有索引。然后让其它服务器从一个统一的地方查询索引。
http://lucene-group.group.javaeye.com/group/topic/23507


亿级数据的高并发通用搜索引擎架构设计 http://blog.s135.com/post/385/
http://lucene-group.group.javaeye.com/group/topic/2786
http://blog.fulin.org/2010/11/search_solutions_compare.html
http://www.javaeye.com/topic/117212
Twitter新搜索架构将采用开源Lucene http://cloud.csdn.net/a/20101008/280220.html?1286504886
用 Lucene构建实时的索引 http://www.cnblogs.com/forfuture1978/archive/2010/06/08/1753642.html
基于lucene实现自己的推荐引擎 http://blog.fulin.org/2010/10/recommendation_system_based_lucene.html
Lucene3.0(2.9)的主要变化 http://www.ourys.com/post/lucene3-0_about.html
Katta is a scalable, failure tolerant, distributed, data storage for real time access.

只有注册用户登录后才能发表评论。


网站导航: