【Elasticsearch】更新操作原理

发布于:2025-05-31 ⋅ 阅读:(18) ⋅ 点赞:(0)

Elasticsearch 的更新操作(如 `_update` 和 `_update_by_query`)在底层实现上有一些复杂的原理,这些原理涉及到 Elasticsearch 的数据存储机制、索引机制以及事务日志(Translog)的使用。以下是 Elasticsearch 更新操作的主要原理:

1. 文档的存储和索引

在 Elasticsearch 中,文档是以 JSON 格式存储的,并且每个文档都有一个唯一的 `_id`。这些文档被存储在索引中,索引由多个分片(Shards)组成,每个分片是一个独立的 Lucene 索引。

2. 更新操作的基本流程

当执行更新操作时,Elasticsearch 会按照以下步骤处理:

a. 查找文档

- Elasticsearch 首先根据提供的 `_id` 在索引中查找目标文档。

- 如果文档不存在,更新操作的行为取决于是否设置了 `doc_as_upsert` 参数:

  - 如果设置了 `doc_as_upsert`,则会插入一个新的文档。

  - 如果没有设置 `doc_as_upsert`,则更新操作会失败。

b. 读取旧文档

- 如果文档存在,Elasticsearch 会读取旧文档的内容。

c. 应用更新

- Elasticsearch 将更新内容(如通过 `_update` API 提供的 `doc` 部分)应用到旧文档上。

- 如果是部分更新(如 `_update`),Elasticsearch 会将新的字段值合并到旧文档中。

- 如果是全量替换(如 `PUT`),Elasticsearch 会用新的 JSON 数据完全替换旧文档。

d. 写入新文档

- 更新后的文档会被重新索引,生成一个新的 Lucene segment。

- 旧文档会被标记为删除(但不会立即从磁盘中删除)。

e. 事务日志(Translog)

- 更新操作会被记录在事务日志(Translog)中,以确保操作的持久性。

- 事务日志是一个持久化的日志文件,用于记录所有对索引的写操作(包括插入、更新和删除)。

f. 刷新和提交

- 当事务日志达到一定大小或时间间隔时,Elasticsearch 会执行 `_flush` 操作:

  - 将内存中的数据和事务日志中的操作持久化到磁盘。

  - 清空事务日志。

- 在 `_flush` 操作之前,Elasticsearch 会先执行 `_refresh` 操作,确保数据在文件系统缓存中可用,从而可以被搜索到。

3. 并发控制

Elasticsearch 使用乐观并发控制机制来处理并发更新:

- 每个文档都有一个序列号(`seq_no`)和一个主版本号(`primary_term`)。

- 在更新操作时,可以指定 `if_seq_no` 和 `if_primary_term` 参数,以确保只有在文档的序列号和主版本号匹配时才执行更新。

- 如果序列号或主版本号不匹配,更新操作会失败,从而避免覆盖其他用户的更改。

4. 批量更新

对于批量更新操作(如 `_update_by_query`),Elasticsearch 会按照以下步骤处理:

- 执行查询,找到需要更新的文档集合。

- 对每个文档应用更新逻辑。

- 逐个更新文档,每个文档的更新过程与单个文档更新类似。

- `_update_by_query` 操作会使用内部的重试机制来处理并发冲突。

5. 性能优化

- 内存管理:Elasticsearch 会将更新操作的结果暂存到内存中,以提高性能。

- 批量处理:对于批量更新操作,Elasticsearch 会尽量减少对磁盘的写入次数,通过批量处理来优化性能。

- 异步处理:某些更新操作(如 `_flush` 和 `_refresh`)是异步执行的,以减少对请求的阻塞。

总结

Elasticsearch 的更新操作涉及多个步骤,包括查找文档、读取旧文档、应用更新、写入新文档、记录事务日志、刷新和提交等。通过这些机制,Elasticsearch 确保了更新操作的高效性、一致性和持久性。同时,通过乐观并发控制机制,Elasticsearch 能够有效处理并发更新,避免数据冲突。