5

我正在使用从 NuGet 安装的 Lucene.net 3.0.3 和 AzureDirectory 2.0.4937.26631(在 NuGet 中称为 Lucene.Net.Store.Azure)。

azuredirectory.codeplex.com上的项目描述声明“更具体地说:您可以让 1..N 个工作人员角色将文档添加到索引,以及 1..N 个搜索者 webroles 近乎实时地搜索目录。” (添加了重点)暗示可以有多个工作角色并行写入索引。但是,当我尝试执行此操作时,我会收到许多“锁定获取超时:AzureLock@write.lock”。例外。

我的代码遵循 AzureDirectory 文档 ( azuredirectory.codeplex.com/documentation ) 中给出的示例。我的代码大致是(简化问题)。

var dbEntities = // Load database entities here
var docFactory = // Create class that builds lucene documents from dbEntities
var account = // get the CloudStorageAccount
var directory = new AzureDirectory(account, "<my container name>");
using(var writer = new IndexWriter(directory, new StandardAnalyzer(Version.LUCENE_30), createEvenIfExists, IndexWriter.MaxFieldLength.UNLIMITED))
{
    foreach(var entity in entities)
    {
       writer.AddDocument(docFactory.CreateDocument(entity));
    }
}

按顺序运行时,此代码工作正常。但是,如果我在多个线程/工作者上并行运行相同的代码。我收到很多“锁定获取超时:AzureLock@write.lock”。例外:

[Lucene.Net.Store.LockObtainFailedException: Lock obtain timed out: AzureLock@write.lock.]
   at Lucene.Net.Store.Lock.Obtain(Int64 lockWaitTimeout) in d:\Lucene.Net\FullRepo\trunk\src\core\Store\Lock.cs:line 83
   at Lucene.Net.Index.IndexWriter.Init(Directory d, Analyzer a, Boolean create, IndexDeletionPolicy deletionPolicy, Int32 maxFieldLength, IndexingChain indexingChain, IndexCommit commit) in d:\Lucene.Net\FullRepo\trunk\src\core\Index\IndexWriter.cs:line 1228
   at Lucene.Net.Index.IndexWriter..ctor(Directory d, Analyzer a, Boolean create, MaxFieldLength mfl) in d:\Lucene.Net\FullRepo\trunk\src\core\Index\IndexWriter.cs:line 1018

我知道在 blob 存储中创建了一个“write.lock”文件,并且当文件包含文本“wrote.lock”时,锁定被持有。我从我的搜索中看到,用户遇到了 write.lock 没有被清理的问题。这似乎不是我的问题,因为我可以让相同的代码在按顺序运行时正常工作,并且在这种情况下会清除锁定文件。

我在 AzureDirectory 文档 ( azuredirectory.codeplex.com/documentation ) 中看到“索引一次只能由一个进程更新,因此通过索引角色推送所有添加/更新/删除操作是有意义的。” 但是,这没有任何意义,因为您创建的任何角色都应该有多个实例,因此会有多个实例并行写入索引。此外,项目描述直接声明“您可以让 1..N 个工作人员角色将文档添加到索引中”。请注意,它说的是“一个”索引,而不是索引碎片。

问题:

那么,项目描述是否完全错误?或者实际上有什么方法可以让多个 IndexWriters 并行添加到索引中?我在 API 中看不到任何允许这样做的内容。如果可能,请提供一个代码片段,说明如何使用 AzureDirectory 并行“让 1..N 个工作角色将文档添加到索引”。

4

1 回答 1

1

最有效的方法是......

1)使用生产者/消费者设计模式

  • 有了这个,您可以拥有 x 数量的线程/任务,每个写入者写入索引
  • 您可以从数据库中读取 x 数量的消费者(即线程/任务)

2) 对于大型索引,生产者/消费者模式应该生成单独的索引。例如,如果我有 4 个作者,我构建 4 个索引,然后我使用 Lucene API 来合并它们

3) 之后你的硬盘上有一个很好的索引。使用 AzureDirectory 的最后一步是使用 Lucene Directory.Copy 命令将索引从 FSDirectory(硬盘驱动器)复制到 Azure 目录。

  • 这很重要,因为 AzureDirectory 在内部使用 Azure Blob 存储上的元数据属性来确定索引的“最后更新指纹”
  • AzureDirectory 还会在上传之前压缩索引……这就是我喜欢将其发送到 Azure Blob 存储之前的硬盘驱动器步骤的原因,因为我可以使用并行线程在硬盘驱动器上压缩它。我更改了 AzureDirectory 的实现,因为它在内存中执行所有操作,并且对于 20 gig 索引这样做并不好 :)

我已将它用于 Azure 中的 IaaS/PaaS 产品,效果很好。请记住,(我之前在帖子中提到过)AzureDirectory 在我看来还没有准备好“企业”或“严肃的生产”......有些事情比如:网络重试、上传大索引、压缩大索引之前需要解决我可以称之为“生产就绪”。如果可以,请使用 IaaS Azure 产品,然后您就不需要 Azure Directory,而是使用 vanilla FSDirectory 来构建/显示您的索引。

于 2013-08-29T01:03:45.677 回答