⚠️ 此页面为自动翻译,翻译可能不完美。

Improvements in Manticore Search 2.7: local indexes management

直到现在,资源共享都是通过读写锁来实现的。在高负载情况下,使用锁机制在尝试对索引进行修改时可能会遇到问题。为了解决这些问题,我们必须重新思考线程与索引之间的关系。

索引可能很大甚至非常大,它们在多个工作进程中共享。在多核 CPU 上,你可以同时发起许多查询,它们会分布在各个核心上,使用同一个索引。这很简单明了。然而,有时你需要更新索引。无缝切换在旧版 fork 工作进程中表现良好:我们只需加载新的索引文件,让正在运行的 fork 进程继续使用旧索引提供服务。在某一时刻,新查询会转向已加载新索引的 fork 进程。因此,服务不会出现延迟:你只需无缝地从旧索引切换到新索引。使用旧版本的进程会完成(或崩溃),最终旧索引会被释放。

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

在 2.7 版本引入的新模型中,索引现在在各个线程之间独立存在,类似于旧版的 fork 情况,因为它们现在既不是 "共享" 也不是 "锁定",而是 不可变的。这使得运行更简单:工作进程只需使用索引,无需关心 "锁定" 或 "共享"。当需要切换(加载新索引)时,守护进程只需执行此操作,无需考虑正在运行的查询(以及它们的线程也无需关心“写入者”)。最终,切换只需将活动索引的指针指向新加载的索引,之后所有操作都与 fork 一样:旧查询仍使用旧索引,新查询则指向刚加载的新索引。唯一仍然需要使用独占锁的情况是执行 UPDATE 操作时。

新模型的另一个优势是,我们可以通过重新加载配置文件,动态更改索引的类型。以前,更改索引类型并不总是可以通过修改配置文件并尝试重新加载(通过 HUP 信号)来实现,例如将“普通”索引切换为“分布式”或“分布式”切换为“模板”。现在,当你重新加载新配置时,其中所有旧索引的内容都保留其名称——守护进程会首先解析新配置。如果新配置可以立即使用(这适用于模板和分布式索引)——它会无缝地进行切换。如果新索引是“重型”(即需要预加载到 RAM 中,可能需要几分钟)——切换过程会延迟到它们加载完成。«延迟» 意味着调用者会看到“ok”返回,“(所有已切换)”。但实际工作进程仍会将所有新查询发送到旧索引,直到新索引最终加载并激活。

安装Manticore Search

安装Manticore Search