14

我们正在为企业 Web 应用程序设计搜索架构。我们将为此使用 Lucene.net。索引不会很大(大约 100,000 个文档),但搜索服务必须始终处于运行状态并且始终处于最新状态。将一直有新文档添加到索引和并发搜索。由于我们必须为搜索系统提供高可用性,因此我们有 2 个应用程序服务器,它们公开 WCF 服务来执行搜索和索引(服务的副本在每个服务器中运行)。然后服务器使用 lucene.net API 来访问索引。

问题是,保持索引始终同步的最佳解决方案是什么?我们考虑了几个选项:

  • 使用一台服务器进行索引并让第二台服务器通过 SMB 访问索引:不行,因为我们有单点故障情况;

  • 对两台服务器建立索引,基本上每个索引都写入两次:可能性能很差,并且可能会出现不同步,例如。服务器 1 索引正常,服务器 2 磁盘空间不足或其他什么;

  • 使用 SOLR 或 KATTA 包装对索引的访问:不,我们不能在服务器上运行 tomcat 或类似的东西,我们只有 IIS。

  • 将索引存储在数据库中:我发现这可以使用 Lucene 的 java 版本(JdbcDirectory 模块)来完成,但我找不到与 Lucene.net 类似的任何东西。即使这意味着对性能的小幅影响,我们也会选择这个选项,因为它可以干净地解决最小开发的并发和同步问题。

  • 使用 Lucene.net DistributedSearch contrib 模块:我无法提交包含有关此文档的单个链接。通过查看代码我什至不知道这段代码做了什么,但在我看来,它实际上将索引拆分到多台机器上,这不是我们想要的。

  • rsync 和朋友,在 2 个服务器之间来回复制索引:这对我们来说感觉很骇人且容易出错,而且,如果索引变大,可能需要一段时间,在此期间我们将返回损坏或不一致数据给客户端,所以我们必须制定一些我们不希望的临时锁定策略。

我知道这是一个复杂的问题,但我相信很多人以前都遇到过。欢迎任何帮助!

4

5 回答 5

8

似乎最好的解决方案是将两台服务器上的文档索引到它们自己的索引副本中。

如果您担心索引在一台服务器上成功而在另一台服务器上失败,那么您需要跟踪每台服务器的成功/失败,以便在问题解决后重新尝试失败的文档。这种跟踪将在 Lucene 之外的任何系统中完成,无论您使用什么系统来呈现要索引到 Lucene 的文档。根据索引的完整性对您的重要性,您可能还必须从正在使用的任何负载均衡器中删除故障服务器,直到问题得到解决并且索引已重新处理任何未完成的文档。

于 2009-06-03T11:50:01.927 回答
2

我知道这是一个老问题,但我只是遇到了它,并想为其他寻求多服务器实施建议的人提供 2 美分。

为什么不将索引文件保存在共享的 NAS 文件夹中?它与您正在考虑的将索引存储在数据库中有何不同?可以复制数据库以实现高可用性,NAS 也可以复制!

我将配置您在负载均衡器后面的两个应用服务器。任何传入的索引请求都将索引 NAS 上机器特定文件夹中的文档。也就是说,NAS 上的索引与您的应用服务器一样多。当一个搜索请求进来时,你将使用 Lucene 进行多索引搜索。Lucene 有内置的构造(MultiSearcher)来做到这一点,并且性能仍然非常出色。

于 2012-02-22T04:59:45.127 回答
1

肖恩·卡彭特的回答 +1。在两台服务器上建立索引似乎是最明智和最安全的选择。

如果您要索引的文档很复杂(Word/PDF 等),您可以在单个服务器上执行一些预处理,然后将其提供给索引服务器,以节省一些处理时间。

我之前使用过的一个解决方案是在一台服务器上创建一个索引块,然后rsync将其传送到搜索服务器,并将该块合并到每个索引中,使用IndexWriter.AddIndexesNoOptimize. 您可以每 5 分钟创建一个新块,也可以在它达到一定大小时创建一个新块。如果您不必拥有绝对最新的索引,这可能是您的解决方案。

于 2009-06-03T12:34:25.113 回答
1

在 Java 世界中,我们通过在索引前面放置一个 MQ 来解决这个问题。仅当从队列中拉出的 bean 成功时插入才完成,否则它只是回滚它采取的任何操作,在 doc 上标记为待处理,稍后再试一次

于 2009-06-13T04:37:05.677 回答
0

我们保持负载平衡服务器同步的方式,每个服务器都有自己的 Lucene 副本,是在其他服务器上执行一个任务,该任务每 5 分钟运行一次,命令每个负载平衡服务器将其索引更新到某个时间戳。

例如,任务向所有负载均衡服务器发送时间戳“12/1/2013 12:35:02.423”(任务通过查询字符串将时间戳提交到每个负载均衡网站上的网页),然后每个服务器使用该时间戳向数据库查询自上次更新到该时间戳以来发生的所有更新,并更新其本地 Lucene 索引。

每个服务器还将时间戳存储在数据库中,因此它知道每个服务器上次更新的时间。因此,如果服务器脱机,当它重新联机时,下次它收到时间戳命令时,它将获取它在脱机时错过的所有更新。

于 2013-11-09T07:31:06.400 回答