我正在使用 Lucene.net 3.0.3.0 (目前是最新版本)。我想知道在生产环境中使用 IndexWriter 和 IndexSearcher 的单个实例是否是一个不错的选择(考虑线程安全性)。我在文档中读到,创建这些实例的新对象是一项昂贵的操作,并且内部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
}
答案 0 :(得分:3)
我的理解是每个索引应该只有1个IndexWriter实例。默认情况下,Lucene中启用了内置锁定以确保此条件。至于单例模式,我认为你应该看看.NET 4中新的Lazy类。它免费处理所有锁定和空检查。
对于IndexSearcher,您可以随意拥有任意数量的实例。但是,如果您重用现有的搜索器,我认为可以获得性能提升。我可以从你的代码中看出,你知道重新打开一个现有的搜索者要比创建一个新搜索者便宜得多。此外,搜索器中还有内置缓存,当您进行第一次搜索时,它会被初始化。您还可以实现IndexReaderWarmer来控制搜索器何时变暖(如第一次搜索之前)。