在 ElasticSearch 中更改别名会返回 200 并已确认,但不会更改别名

Loc*_*Ann 6 java rest http opensearch elasticsearch

使用带有 Java 17 的 elasticsearch 8.4.3 和一个由 3 个节点组成的集群,其中 3 个节点符合主节点条件,我们从以下情况开始:

  • 索引products-2023-01-12-0900其别名为current-products

然后我们开始一项创建新索引products-2023-01-12-1520 的工作,最后在客户端使用elastic-rest-client和别名 API,我们进行以下调用:

于 2023 年 1 月 12 日 16:27:26,893:

POST /_aliases
{"actions":[
   {
    "remove": { 
       "alias":"current-products",
       "index":"products-*"
    }
   },
   { 
    "add":{
       "alias":"current-products",
       "index":"products-2023-01-12-1520"}
    }
]}
Run Code Online (Sandbox Code Playgroud)

26 毫秒后,我们得到以下响应,HTTP 响应代码为 200:

{"acknowledged":true}
Run Code Online (Sandbox Code Playgroud)

但看看我们最终得到的结果,我们仍然有带有当前产品别名的旧索引。

我不明白为什么会发生这种情况,而且它不会 100% 发生(大约 10 次索引中发生了 2 次)。这是一个已知的错误吗?还是一种常规行为?

编辑@warkolm:

截至目前,在索引之前获取 /_cat/aliases?v :

alias               index                       filter routing.index routing.search is_write_index
current-products    products-2023-01-13-1510    -      -             -              -
Run Code Online (Sandbox Code Playgroud)

Pre*_*col 1

您更新别名的方式似乎可能存在问题。当您使用“删除”和“添加”操作向 _aliases 端点执行 POST 请求时,Elasticsearch 将根据执行请求时索引的当前状态更新别名。

但是,可能有其他进程或操作同时修改索引或别名,这可能会导致冲突或不一致。此外,当您在“删除”操作的“索引”字段中使用通配符 (*) 时,它将从与模式匹配的所有索引中删除别名,这可能不是预期的行为。

为了避免此问题,您可以尝试使用索引别名 API 而不是 _aliases 端点。此 API 允许您对别名执行原子更新,这意味着仅当所有操作成功时才​​会更新别名,如果任何操作失败则将回滚。此外,您可以显式指定要从中删除别名的索引,而不是使用通配符。

以下是如何使用索引别名 API 更新别名的示例:

POST /_aliases
{
    "actions": [
        { "remove": { "index": "products-2023-01-12-0900", "alias": "current-products" } },
        { "add": { "index": "products-2023-01-12-1520", "alias": "current-products" } }
    ]
}
Run Code Online (Sandbox Code Playgroud)

这样,别名只会从特定索引“products-2023-01-12-0900”中删除,并添加到特定索引“products-2023-01-12-1520”中。这可以帮助避免可能由同时修改索引或别名的其他进程或操作引起的任何冲突或不一致。

此外,建议使用等于或高于 8.4.3 的 Elasticsearch 版本,因为它修复了许多错误,这些错误可能是导致您遇到问题的原因。

总之,您遇到的问题可能不是已知的错误,但如果多个进程同时修改索引或别名,并使用索引别名 API 并指定确切的索引来删除或添加别名,则这是一种常规行为可以帮助避免这个问题。