Manticore Search 2.7 的改进:本地索引管理

资源共享到目前为止是通过 RW 锁完成的。在高负载下,使用锁在尝试对索引进行更改时可能会遇到问题。为了克服这些问题,我们必须重新思考线程与索引之间的关系。

索引可以很大甚至巨大,并且它们在工作线程之间共享。在多核 CPU 上,您可以同时发出许多查询,它们将分布在核心上,使用同一个索引。这很简单明了。然而,有时您需要更新索引。无缝轮换在旧的 fork 工作线程中运行得相当好:我们只需加载新的索引文件,让正在工作的进程继续使用旧的索引。在某一时刻,新查询会发送到已经共享新加载索引的进程。因此,在服务中没有延迟:您只需无缝地从旧索引切换到新索引。使用旧版本的工作线程将完成(或崩溃),因此,最终之前的索引将被释放。

在线程工作线程的情况下,使用了简单的 RW 锁 - '共享-独占锁' - 机制,其中许多共享工作线程(读取者)可以同时访问资源,但一个独占工作线程(写入者)可以修改它。因此,索引始终是 '共享' 的,或者在轮换时 '锁定'。它们在开始时加载,在结束时释放。当进行轮换时,一个线程加载新的索引,但它需要对活动索引描述符的独占访问。然而,查询工作线程具有共享访问权限,没有人会阻止它们获取新任务。这意味着在高负载下,您无法执行“无缝”轮换,因为它的最后一步 - 原子性地将旧索引更改为新索引。

在 2.7 中引入的新模型中,索引现在在线程之间独立存在,类似于旧的 'fork' 情况,因为它们现在既不是 '共享' 也不是 '锁定',而是 不可变 的。因此,这使得运行更简单:工作线程只需使用索引,而不必关心 '锁定' 或 '共享'。当您需要轮换(加载新索引)时,守护进程只需执行此操作,而不必关心正在运行的查询(它们的线程也不必关心 '写入者')。最终,轮换只是将活动索引的指针切换到新的(已加载的)索引,然后一切就像使用进程一样:旧查询仍然使用先前的索引,新查询指向刚加载的索引。唯一仍然使用独占锁的情况是进行 UPDATE 时。

新模型的另一个优点是我们可以通过配置重新加载动态更改索引的类型。之前,通过更改配置文件并尝试重新加载(通过 HUP 信号)来更改索引的类型并不总是可行,例如将 'plain' 索引切换为 'distributed' 或 'distributed' 切换为 'template'。现在,当您重新加载新配置时,旧索引的所有内容都是它的名称 - 守护进程将首先解析新的配置。如果它可以立即使用(对于模板和分发的情况) - 它将无缝地进行交换。在新索引是 ''(即需要预缓存到 RAM 中,可能需要几分钟)的情况下 - 轮换过程将推迟,直到它们加载完成。«推迟» 意味着调用者看到 'ok' 返回,'(所有已轮换)'。但实际工作线程仍将向旧索引发出所有新查询,直到新的索引最终加载并激活。

安装Manticore Search

安装Manticore Search