5

我正在使用Lucene.net 3.0.3.0(现在是最新版本)。我想知道在生产环境中使用IndexWriterIndexSearcher的单个实例是否是一个不错的选择(考虑到线程安全)。我在文档中读到,创建这些实例的新对象是一项昂贵的操作,并且内部 lucene 可以很好地处理并发请求。

这是在生产环境中使用过 lucene.net 的人的一个问题;请让我知道这是否会成功!

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Lucene.Net.Search;
    using Lucene.Net.Store;
    using System.IO;

    using Directory = Lucene.Net.Store.Directory;
    using Version = Lucene.Net.Util.Version;
    using Lucene.Net.Index;
    using Lucene.Net.Analysis.Standard;
    using Lucene.Net.Analysis;

    namespace MXLuceneConsoleApp
    {
        /// <summary>
        /// This helper class applies a singleton pattern to create Searcher and Writer objects as it's recommended to create them only once.
        /// Also the searcher gets reinitialized, if any write happens.    
        /// </summary>
        public class MXLuceneIndexHelper
        {
            private static IndexSearcher _searcher;        
            private static Directory _directory;
            private static Lazy<IndexWriter> _writer = new Lazy<IndexWriter>(() => new IndexWriter(_directory, new StandardAnalyzer(Version.LUCENE_30), IndexWriter.MaxFieldLength.UNLIMITED));

            //this private constructor makes it a singleton now.
            private MXLuceneIndexHelper() { }

            //Static constructor, opening the directory once for all.
            static MXLuceneIndexHelper()
            {
                _directory = FSDirectory.Open(new DirectoryInfo(Environment.CurrentDirectory + "\\LuceneIndexDir"));
            }

            public static IndexSearcher IndexSearcher
            {
                get
                {
                    if (_searcher == null)
                    {
                        InitializeSearcher();
                    }
                    else if (!_searcher.IndexReader.IsCurrent())
                    {                    
                        //_searcher.IndexReader.Reopen(); 
                        //refreshing the underlying Reader above doesn't do the trick, so I'm reinitializing the Searcher.
                        _searcher.Dispose();
                        InitializeSearcher();
                    }

                    return _searcher;
                }
            }

            public static IndexWriter IndexWriter
            {
                get 
                {                
                    //_writer.SetRAMBufferSizeMB(30.0);
                    return _writer.Value; 
                }
            }

            private static void InitializeSearcher()
            {
                _searcher = new IndexSearcher(_directory, false);

            }
        }//End of class
    }
4

1 回答 1

3

我的理解是每个索引应该只有 1 个 IndexWriter 实例。默认情况下,Lucene 中启用了内置锁定以确保这种情况。至于单例模式,我认为您应该看看 .NET 4 中的新Lazy类。它免费处理所有锁定和空检查。

至于 IndexSearcher,您可以随意拥有任意数量的实例。但是,我认为如果您重用现有的搜索器,性能会有所提高。我可以从您的代码中看出,您知道重新打开现有搜索器比创建新搜索器便宜得多。当您进行第一次搜索时,搜索器中也有内置缓存。您还可以实现 IndexReaderWarmer 来控制搜索器何时被加热(如在第一次搜索之前)。

于 2013-01-23T14:42:36.053 回答