专用写进程,在另一个进程中只有读取器
本文关键字:进程 读取 另一个 专用 | 更新日期: 2023-09-27 18:02:56
我正在做一个ASP。. Net MVC 5应用程序,使用Lucene.net实现全文搜索。
由于在ASP中托管后台任务的潜在问题。在网上,我正在考虑以下场景是否可行:
- 将唯一的Lucene写入器移动到一个专门的进程,该进程定期检查数据库中未索引的行并相应地更新Lucene索引
- 将阅读器保存在ASP中。. NET工作进程
使用FSDirectory是否有效?
我认为这是可能的。你可以同时拥有多个indexreader,这应该没问题,它甚至有一个外部锁特性(基于文件系统)用于多进程锁定。
记住,IndexReader会从创建时开始搜索当前的"快照",所以当索引发生变化时,你应该找到一种方法来"转储"IndexReader。当然,您可以为每个搜索创建一个IndexReader,但可能不建议这样做,如果您当前正在写入索引,则会失败。出于这些目的,您可以从当前的写入器中检索读取器,但这不是您的选择,因为它们将驻留在不同的进程中。
您可能也会觉得这篇文章很有趣:
http://devlearnings.wordpress.com/2010/04/26/lucene-reuse-indexsearcher-rather-creating-new-everytime/在我为这个项目编写的一个小助手类的帮助下,我已经设法使这个工作很好。下面的工厂类与任意数量的线程共享一个indexReader,并确保从GetCurrentReader()返回的reader与索引的状态保持同步。
class IndexReaderFactory :
IDisposable
{
public IndexReaderFactory(bool isReadonly)
{
this.isReadonly = isReadonly;
}
IndexReader reader;
readonly ReaderWriterLockSlim rwl = new ReaderWriterLockSlim();
private readonly bool isReadonly;
/// <summary>
/// Returns a reader that isCurrent
/// </summary>
public IndexReader GetUpToDateReader()
{
rwl.EnterUpgradeableReadLock();
try
{
if (reader == null)
{
rwl.EnterWriteLock();
try
{
if (logger.IsInfoEnabled)
logger.Info("Creating IndexReader on directory {0}", AppSettingsBase.LucenePostIndexLocation);
reader = IndexReader.Open(FSDirectory.Open(AppSettingsBase.LucenePostIndexLocation), isReadonly);
}
finally
{
rwl.ExitWriteLock();
}
}
else if(!reader.IsCurrent())
{
rwl.EnterWriteLock();
try
{
if (logger.IsInfoEnabled)
logger.Info("IndexReader is not current. Re-opening");
reader = reader.Reopen();
}
finally
{
rwl.ExitWriteLock();
}
}
}
finally
{
rwl.ExitUpgradeableReadLock();
}
return reader;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public void Dispose(bool disposing)
{
if (disposing)
{
// get rid of managed resources
}
if(reader != null)
reader.Dispose();
}
}