【问题标题】:Dedicated writer process with only readers in another process专用的写入器进程,只有另一个进程中的读取器
【发布时间】:2014-05-12 09:05:22
【问题描述】:

我正在开发一个使用 Lucene.net 实现全文搜索的 ASP.Net MVC 5 应用程序。

由于potentional problems 在 ASP.Net 中托管后台任务,我正在思考以下方案是否可行:

  1. 将唯一的 Lucene 写入器移至专用进程,该进程会定期检查数据库中未索引的行并相应地更新 lucene 索引
  2. 让读者留在 ASP.NET 工作进程中

使用 FSDirectory 会起作用吗?

【问题讨论】:

    标签: c# .net asp.net-mvc lucene.net


    【解决方案1】:

    我认为这是可能的。您可以同时拥有多个 IndexReader,应该没问题,它甚至具有用于多进程锁定的外部锁定功能(基于文件系统)。

    请记住,IndexReader 将从创建时开始在当前“快照”中进行搜索,因此您应该找到一种在索引更改时“转储”IndexReader 的方法。您当然可以为每个搜索创建一个 IndexReader,但可能不推荐这样做,如果您当前正在写入索引,则会失败。出于这些目的,您可以从当前写入者中检索读取器,但这不是您的选择,因为它们将驻留在不同的进程中。

    您可能也会觉得这篇文章很有趣:

    http://devlearnings.wordpress.com/2010/04/26/lucene-reuse-indexsearcher-rather-creating-new-everytime/

    【讨论】:

    • 如果当前正在写入索引,为什么您认为打开阅读器会失败?
    • @OliverWeichhold 好吧,也许它不会失败,但您最终可能会处于阅读器没有索引或不一致状态的状态。我真的不记得锁是如何影响读者的。
    【解决方案2】:

    在我为该项目编写的一个小助手类的帮助下,我已经成功地完成了这项工作。下面的工厂类与任意数量的线程共享一个 indexReader,并确保从 GetCurrentReader() 返回的读取器与索引的状态保持同步。

    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();
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-15
      • 2013-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多