问答题830/1053详细描述一下Elasticsearch更新和删除文档的过程

难度:
2021-11-02 创建

参考答案:

在 Elasticsearch 中,更新和删除文档的过程与插入文档有一些不同。虽然它们都涉及到文档在 Elasticsearch 中的存储和管理,但具体的实现方式和细节有所区别。以下是 Elasticsearch 更新和删除文档的详细过程。

1. 更新文档的过程

Elasticsearch 在进行文档更新时,并不会直接修改已存储的文档,而是通过以下步骤进行“更新”操作:

1.1 Elasticsearch 的更新策略

更新文档的实际过程是通过 删除旧文档插入新文档 实现的。这个操作的核心思想是 不可变性,即文档一旦被写入,就不会被修改,修改实际上是创建一个新的文档,并删除旧的文档。

具体更新流程如下:

1.2 更新文档的请求

更新文档通常使用 update API 来进行操作。它通常包含两部分:

  • doc:包含需要更新的字段和新的值(仅更新部分字段,不更新整个文档)。
  • upsert:如果文档不存在,指定的文档将会被插入。

例如,更新某个文档的某个字段:

1POST /index_name/_update/document_id 2{ 3 "doc": { 4 "field1": "new_value" 5 } 6}

如果文档不存在,则可以使用 upsert 来插入新文档:

1POST /index_name/_update/document_id 2{ 3 "doc": { 4 "field1": "new_value" 5 }, 6 "upsert": { 7 "field1": "new_value", 8 "field2": "default_value" 9 } 10}

1.3 更新请求的执行

当更新请求到达 Elasticsearch 集群时,处理过程如下:

  1. 路由到正确的分片:更新请求通过路由机制被路由到包含目标文档的分片。如果没有指定路由,则使用默认的 _id 进行路由。

  2. 删除旧文档:在分片上,Elasticsearch 会首先删除具有相同 _id 的文档。实际上,文档并不会立即从磁盘删除,而是被标记为删除。Lucene 会将该文档标记为“删除标记”,即 soft delete。这意味着它在物理层面上并没有立刻从磁盘中移除,但它在后续的查询和索引更新中将被忽略。

  3. 插入新文档:随后,Elasticsearch 会将新的文档插入到索引中。这是一个插入新文档的过程,实际上是将新文档写入分片中的倒排索引,并根据新的文档重新计算倒排索引。

  4. 更新文档版本:在 Elasticsearch 中,每个文档都有一个版本号。当更新文档时,版本号会自增,表示该文档是一个新的版本。Elasticsearch 使用版本控制机制来保证文档更新时的并发一致性。

1.4 文档更新的性能考虑

  • 更新并非原子操作:Elasticsearch 的更新操作不是原子操作,因为它先删除文档,再插入新文档。这可能在高并发场景下导致性能瓶颈或“丢失更新”问题。
  • 延迟写入:在一些情况下,文档的删除标记和新文档的插入会产生延迟。这是因为 Elasticsearch 在优化存储时会合并和清理旧的删除标记,这会消耗更多的资源。

2. 删除文档的过程

删除文档的过程与更新文档的部分流程相似。删除文档的核心操作是 标记删除,并在后台定期清理。

2.1 删除文档的请求

删除文档通常使用 delete API 来执行,格式如下:

1DELETE /index_name/_doc/document_id

这个请求会从 Elasticsearch 中删除指定的文档。

2.2 删除请求的执行

当删除请求到达 Elasticsearch 集群时,处理过程如下:

  1. 路由到正确的分片:和更新操作一样,删除请求也通过路由机制路由到正确的分片。

  2. 标记文档为删除:Elasticsearch 会将目标文档标记为删除。实际上,Lucene 会对文档进行“软删除”(soft delete),即不会立即从磁盘上物理删除该文档,而是将其标记为删除。这个操作相对快速,Elasticsearch 会更新文档的元数据,标记它为已删除。

  3. 删除标记和删除合并:Elasticsearch 会将删除标记保留在内存中,并在适当的时候(如段合并操作)物理删除这些文档。在 Elasticsearch 的背景中,这一过程称为 segment merge,即将多个小的索引段合并为一个更大的索引段。在这个过程中,所有标记为删除的文档会被移除,释放磁盘空间。

2.3 删除文档的性能考虑

  • 删除操作并不影响搜索结果:删除文档实际上只是将文档标记为删除,直到后续的合并操作才会真正清理这些文档。因此,删除操作对于查询性能没有即时影响,查询时仍然会忽略已删除的文档。
  • 垃圾回收(GC):删除标记的文档需要通过 segment merge 操作才能完全清除。由于 Elasticsearch 的索引文件可能会变得非常大,因此必须定期进行 segment merge 操作,以避免存储空间的浪费。

3. 关于版本控制和并发问题

在进行更新或删除操作时,Elasticsearch 会使用版本控制来防止并发修改问题。每次更新都会增加文档的版本号。默认情况下,Elasticsearch 会在更新时校验版本,确保没有并发更新操作。版本号的存在确保了更新操作的顺序一致性,避免丢失数据或覆盖更新。

3.1 版本控制机制

  • 乐观锁:每次更新或删除文档时,Elasticsearch 会检查文档的版本号。通过校验版本号来判断是否存在并发修改。如果版本不一致,Elasticsearch 会返回版本冲突错误。
  • 版本冲突处理:如果两个客户端同时更新同一个文档,且版本不一致,Elasticsearch 会返回版本冲突错误。客户端可以通过重试或其他方式解决冲突。

4. 更新和删除文档的高效性

虽然更新和删除文档的过程看似复杂,但 Elasticsearch 通过以下方式优化了这些操作:

  • 分布式和并行处理:更新和删除操作在集群中是分布式执行的,可以并行处理大量请求。
  • 写时复制和写时合并:通过写时复制(write-once)和写时合并(segment merge)等机制,Elasticsearch 可以高效地管理和清理文档,提高写入性能。
  • 背景清理任务:在后台,Elasticsearch 会定期进行删除标记的清理操作,确保索引文件的空间不会被浪费。

最近更新时间:2024-12-12