
Meilisearch v0.30 于本月早些时候发布。我们的首要目标是使 Meilisearch 工作流程尽可能顺畅。毕竟,我们正在迈向 v1,我们的目标比以往任何时候都更近。为此,实现零停机时间的索引部署是至关重要的一步。我们很高兴地宣布,v0.30 解决了这个问题,使在生产环境中更新索引变得前所未有的简单。请继续阅读,了解此功能的工作原理!
挑战
假设您在数据库中有需要与生产环境中的 Meilisearch 索引同步的更改。您会怎么做?如果您在 Meilisearch v0.29 上工作,您可能会
更新您的索引
🙅♀️ 简单,对吧?但是如果你尝试过,那么你应该已经知道…
在生产环境中更新索引,同时它接收搜索查询,可能导致结果不一致甚至信息缺失。您不想提供那样的搜索体验,对吗?否则,您就不会使用 Meilisearch 😁
删除索引,创建同名新索引,然后重新索引数据
⌛ 每个步骤都需要一些时间。即使只有几秒钟,那也是几秒钟的停机时间……而且至少有三个请求!几秒钟这里加上几秒钟那里,可能导致几分钟的停机时间!不,非常感谢。
创建新索引并使用不同的名称,在那里暂存更改,然后修改所有客户端以指向新索引
🤔 嗯,这不是最糟糕的选择。但同样,更新客户端会导致停机😞 在某些情况下,客户端更新何时推送到生产环境甚至不由开发人员决定。以 iOS 应用程序为例:Apple 必须在您发布新版本之前进行审核,这可能会严重拖慢您的发布计划。
创建一个中间重定向层以避免停机
🧞 非常聪明!虽然这是一个好方法,但它不是最直接的方法。它需要架构知识、时间和额外的工具。
您是否很高兴再也不必做这些事情了?
银弹
Meilisearch 一直致力于提供最佳的开发者体验。
我们的团队在过去几个月里一直努力工作,经过多次迭代,他们找到了一种无缝集成到开发者技术栈中的解决方案:索引交换。
让我来向您展示它的工作原理。
假设您有一个生产环境中的索引——indexA
——您的客户端在其中搜索。您想要将主数据库中的更改与 Meilisearch 同步。为此,您将遵循以下步骤。
步骤1:创建包含最新数据的新索引
首先,您需要创建一个索引——我们称之为indexA_new
——它代表您想要部署到搜索客户端的indexA
的新版本。添加数据库中的最新文档,并根据需要更新索引设置。
别忘了检查所有与索引创建相关的任务是否已成功完成,包括indexCreation
、settingsUpdate
和documentAdditionOrUpdate
任务类型。您可以使用/tasks
路由来获取它们的进度信息。
步骤2:测试新索引
在将索引发送到生产环境之前,您需要确保一切都按预期工作。
确保为您使用更新数据引入的任何新字段更新设置。例如,您可能希望将新字段添加到searchableAttributes
、filterableAttributes
和/或sortableAttributes
。每次添加新数据时,都不要忘记仔细检查搜索结果的相关性!
👉 请记住,searchableAttributes
列表不仅指定了可搜索的字段,还规定了属性排名顺序。确保您可能引入的任何新字段都以正确的顺序添加到列表中。
步骤3:交换索引
一旦您的 indexA_new
成功创建、填充数据并经过测试,就可以通过索引交换进行部署了。为此,向 /swap-indexes
端点发送一个 POST
请求。在有效负载中指定您要交换的索引。由于是交换,顺序无关紧要。
curl -X POST 'https://:7700/swap-indexes' -H 'Content-Type: application/json' --data-binary '[ { "indexes": ["indexA", "indexA_new"] } ]'
👉 在一个受保护的 Meilisearch 实例中,用于交换索引的 API 密钥必须具有indexes.swap
操作以及您要交换的索引的访问权限。否则,Meilisearch 将抛出invalid_api_key
错误。有关创建具有特定权限的 API 密钥的更多信息,请参阅文档。
您可以使用响应的taskUid
通过GET /tasks/{task_uid}
端点跟踪请求状态。成功的索引交换应如下所示
{ "uid": 23, "indexUid": null, "status":"succeeded", "type":"indexSwap", "details":{ "swaps": [ {"indexes": ["indexA", "indexA_new"]}, ] }, "duration": "PT1S", "enqueuedAt": "2021-08-10T14:29:17.000000Z", "startedAt": "2021-08-10T14:29:18.000000Z", "finishedAt": "2021-08-10T14:29:19.000000Z" }
您的索引已在没有任何停机的情况下交换成功!indexA
的文档、设置和任务历史(除了任何已排队的任务)已与indexA_new
的交换。任务历史中所有提及indexA
的地方都被indexA_new
取代,反之亦然(enqueued
任务保持不变)。
交换后,indexA_new
包含过时内容。您可以删除它,或将其保留作为备份,以防出现问题需要换回。小心总比后悔好!
就是这样!只需三个步骤,如果你喜欢冒险,也可以是两个。这还能更棒吗?
锦上添花——是的,是复数——🍰
如果我告诉您,只需一个请求,您就可以交换多个索引呢?
我没开玩笑。一个请求可以交换任意数量的索引对。Meilisearch 可以同时且原子地部署所有更改。客户端将立即访问所有索引的新版本,而不会造成任何停机。
curl -X POST 'https://:7700/swap-indexes' -H 'Content-Type: application/json' --data-binary '[ { "indexes": ["indexA", "indexA_new"] }, { "indexes": ["indexB", "indexB_new"] }, { "indexes": ["indexC", "indexC_new"] } ]'
在上面的示例中,三个交换操作将同时原子地发生。
等等,什么?
是的,您可以再读一遍。它是原子性的!要么所有索引都成功交换,要么一个都没有。要么所有内容都交换了,要么都没有。
这为什么重要?它能防止数据库中的部分更改,确保一致性,从而提供一流的搜索体验。
结论
正如我之前提到的,这个功能已经开发了几个月,这一切都始于用户反馈。我们路线图上的“交换索引”卡片获得了 38 票,以及几乎同样多的评论,解释了此功能必不可少的使用场景。以下是我们最喜欢的一些:
- “在尝试更改生产数据库规则以获得最佳结果时,这将非常有用”
- “如果索引意外创建了错误的名称,或者出于各种原因需要重命名/更改它,这将有所帮助。”
- “我们需要它来清除所有已删除的项目。”
这些仅仅是几个例子。这种见解对我们的团队非常有帮助,因为它使我们能够根据用户的需求来塑造产品。
虽然非常方便——您可以全面了解所有已提交、正在制作和已发布的功能想法——但路线图只是提供反馈的一种选择。
在我看来,GitHub 上的产品讨论是解释您需求的最佳场所之一。您可以与 Meilisearch 产品团队直接联系,而且由于它是公开的,任何人都可以参与并丰富这个过程。
最后一个选择是我们的全新Discord 服务器。请毫不犹豫地加入我们,聊聊您用 Meilisearch 做了什么,您的用例,以及您的具体需求。
无论您选择哪种方式,我们都期待您的来信!