在做一個網站站內搜索中,使用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.