type
status
date
slug
summary
tags
category
password

1、文档(Document

1.1 文档是什么

Elasticsearch 中的文档(Document)是存储在索引中的基本数据单元,可以理解为是 Elasticsearch 中最小的数据实体。文档类似数据库的一条数据记录。文档以 JSON 格式表示,被索引后可以被搜索、查询和分析,每个文档都有一个唯一的 ID。
一个典型的文档可能如下所示:
文档的特性:
  • 不可变性:文档一旦被索引就是不可变的,更新操作实际上是删除旧文档并创建新文档。
  • 版本控制:每次修改文档都会增加版本号,支持乐观并发控制。

1.2 文档操作

1.2.1 创建(索引)文档

1、索引新文档(自动生成ID)
2、索引新文档(指定 ID)

1.2.2 查看文档

文档的元数据字段如下:
  • _index:文档所属索引名称。
  • _type:文档所属类型名。
  • _id:文档的主键。在写入的时候,可以指定该文档的 ID 值,如果不指定,则系统自动生成一个唯一的 UUID 值。
  • _version:文档的版本信息。Elasticsearch 通过使用 version 来保证对文档的变更能以正确的顺序执行,避免乱序造成的数据丢失。
  • _seq_no:严格递增的顺序号,每个文档一个,Shard 级别严格递增,保证后写入的文档的_seq_no大于先写入的文档的 _seq_no
  • _primary_term:和_seq_no一样是一个整数,每当 Primary Shard 发生重新分配时,比如重启,Primary 选举等, _primary_term 会递增1
  • found:如果查找了数据就返回 tue,就查不到数据,found 字段就是 false。
  • _source:属性保存了文档的原始 JSON 数据。

1.2.3 更新文档

1、完全替换
2、部分更新

1.2.4 删除文档

1.2.5 批量操作

Bulk API 允许在单个请求中执行多个索引/创建/更新/删除操作,大幅提高操作效率。

2、文档的处理过程

1.1 新增(索引)文档的流程

当我们执行下面语句新增索引)文档的时候,就会执行文档的索引流程。索引文档有两种方式:
Elasticsearch 的索引文档过程涉及从文档进入系统到最终被索引和搜索的全过程,包含以下处理阶段:
  1. 文档接收阶段
      • 客户端请求:通过 REST API 发送文档(PUT/POST)
      • 协调节点:Client 将请求发送到任意节点 Node,此时 Node 节点就是协调节点(Coordinating Node)。协调节点是 Elasticsearch 集群中的一种特殊节点角色,负责处理客户端请求并将这些请求路由到正确的数据节点,协调节点本身不执行文本分析、索引或搜索等实际计算。默认情况下,所有节点都具备协调功能。
      • 路由确定:协调节点根据文档 ID 或路由策略确定目标分片,计算公式为shard_num = hash(routing) % num_primary_shards ,routing 默认是文档 ID。
  1. 分片处理
      • 主分片写入:首先向主分片写入数据。第 1 步得到的目标分片是主分片,查找主分片所在的节点 Node,这个节点 Node 就是数据节点由数据节点执行预处理、文本分析和索引等操作
      • 副本分片同步:主分片处理完成后,找到副本分片所在的节点 Node,异步复制到所有副本分片。
      • 确认机制:向协调节点返回写入成功的响应,协调节点再向 Client 返回成功响应。根据wait_for_active_shards参数等待确认。
  1. 预处理阶段
      • 文档验证:检查 JSON 格式和字段类型
      • 动态映射:如果索引不存在或字段未定义,自动创建映射
      • 字段提取:解析文档中的各个字段
  1. 分析阶段(文本字段)
      • 字符过滤器:处理原始文本(如去除HTML标签)
      • 分词器:将文本拆分为词条(tokens)
      • Token过滤器:对词条进行处理(小写化、同义词、停用词等)
  1. 索引阶段
      • 倒排索引构建:创建 term → document 的映射
      • 正排索引构建:存储原始字段值用于聚合和高亮
      • Doc Values生成:列式存储用于排序和聚合
      • 存储原始文档:可选地存储整个原始文档
  1. 刷新与提交
      • 内存缓冲区:新文档首先写入内存缓冲区(In-memory buffer)
      • 刷新(Refresh):定期(默认1秒)将缓冲区内容转为可搜索的段(segment)
      • 段合并:后台合并小段以提高性能
      • 事务日志:写入操作同时记录到 translog 以保证持久性
      • 提交(Flush):定期将内存中的段持久化到磁盘
notion image

1.2 查找文档的流程

查找文档是指使用文档 ID 查找文档的过程,例如
查找文档的过程有点类似于索引文档的过程,因为有 routing 键,可以计算出数据所在的分片。
notion image
  1. Client 将请求发送到任意节点 node,此时 node 节点就是协调节点(coordinating node)。
  1. 协调节点根据以下计算公式获取目标分片: shard_num = hash(routing) % num_primary_shards ,routing 默认是文档的 id。
  1. 得到的目标分片是 primary shard,使用随机轮询算法,在 primary shard 和 replica shard 之间随机选择一个。
  1. 从选择的 shard 上获取文档,并把文档返回给协调节点。
  1. 协调节点向 Client 返回文档数据。

1.3 检索文档的流程

检索文档和查找文档的过程是不同的。
  • 查找数据是已知文档 ID,我们可以根据文档 id 直接查找文档内容。
  • 检索数据是根据某些关键字来检索,所以需要增加一个查找文档 id 的过程。
检索文档一般使用以下语句:
notion image
检索文档的过程分为两个阶段(Query Then Fetch):
  1. 第一阶段,目标是查询到匹配的文档 ID。
    1. Client 将请求发送到任意节点 node,此时 node 节点就是协调节点(coordinating node)。
    2. 协调节点解析查询请求(包括分词、过滤、排序、分页等),将查询转换为 Lucene 查询语法。
    3. 协调节点确定需要搜索哪些 shard(根据索引和路由信息),每个 shard 使用轮询算法在 primary shard 和 replica shard 选择一个。
    4. 每个 shard 在本地执行以下查询,将满足条件的数据(文档 ID、排序字段等)信息返回给协调节点。
      1. 使用倒排索引查找匹配的文档
      2. 计算文档的相关性评分(使用TF/IDF或BM25算法)
      3. 应用过滤条件、排序等
      4. 返回Top N结果(基于分页参数)
  1. 第二阶段(可选),如果查询要求返回 _source 字段,协调节点会查询文档 ID 对应的完整文档,这一阶段类似于文档的查找过程。
    1. 协调节点重新进行排序,截取数据后,获取到真正需要返回的文档 ID。
    2. 根据文档 ID 再次请求对应的 shard,获取文档返回协调节点。
    3. 协调节点向 Client 返回数据。

1.4 更新/删除文档的流程

Elasticsearch 中的文档是无法直接更新的。我们通常说的对 Elasticsearch 中的文档进行更新,实际上是对指定的文档进行重新索引,也就是将原有的文档进行标记删除,然后再重新索引一个新的文档
例如 id 为 1 的文档已经存在,我们仍然可以执行下面的更新语句
删除文档的过程:磁盘上的每个段都有一个相应的 .del 文件。当删除请求发送后,文档并没有真的被删除,而是在 .del 文件中被标记为删除。该文档依然能匹配查询,但是会在结果中被过滤掉。当段合并时,在 .del 文件中被标记为删除的文档将不会被写入新段。
更新文档的过程:在新的文档被创建时,Elasticsearch 会为该文档指定一个版本号,当执行更新时,旧版本的文档在 .del 文件中被标记为删除,新版本的文档被索引到一个新段。旧版本的文档依然能匹配查询,但是会在结果中被过滤掉。

3、近实时搜索机制

Elasticsearch 的近实时搜索(Near real-time search)是指向 Elasticsearch 插入文档后,默认会要等 1s 后才能搜索到插入的文档。Elasticsearch 不像关系型数据库一样,通过事务和隔离性来控制数据的可见,执行数据插入以后立刻就能搜索到刚刚插入的数据。Elasticsearch 主要用于大数据量和复杂场景的检索或聚合能力,近实时也是为了提高索引和检索的性能。官方文档参考:
近实时搜索机制的几个重要概念:
  • Memory Buffer:内存缓冲区,Elasticsearch 每当有新写入数据,都将数据写入 Memory Buffer,在 Memory Buffer 中的数据既不能被搜索,也没有被持久化。
  • Filesystem Cache:Elasticsearch 定时(默认1s)将 Memory Buffer 中的数据写入一个新的 segment 文件中,并进入操作系统缓存 Filesystem Cache,同时清空 Memory Buffer。在 Filesystem Cache 中的数据可以被搜索到,但是还没有进行持久化。所以 Elasticsearch 的新增数据的搜索并不是实时的,而是近实时搜索。
  • Translog:由于 Memory Buffer 和 Filesystem Cache 都是基于内存,假设服务器宕机,那么数据就会丢失,所以 Elasticsearch 通过 Translog 日志文件来保证数据的可靠性。在数据写入 Memory Buffer 的同时,将数据也写入 Translog 日志文件。当机器宕机重启时,Elasticsearch 会自动读取 Translog 日志文件中的数据,恢复到 Memory Buffer 和 Filesystem Cache 中去。Translog 以追加写的方式写入,所以性能很高。默认每隔 5s fsync 到硬盘,fsync 前如果宕机了最多丢失 5s 的数据。

3.1 近实时的工作原理

数据落盘完整过程是 write -> refresh -> flush -> merge
notion image
  1. write 过程:写入 Memory Buffer 的,同时写入 Translog,这时候数据还不能被搜索到。Translog 也是先写入 Filesystem Cache,然后默认每隔 5 秒刷一次到磁盘中,所以默认情况下,可能有 5 秒的数据会仅仅停留在 Memory Buffer 或者 Translog 文件的 Filesystem Cache中,而不在磁盘上,如果此时机器宕机,会丢失 5 秒钟的数据。
    1. notion image
  1. refresh 过程:每隔一段时间时间(由 index.refresh_interval 控制,默认1s),执行一次 refresh 操作,将所有 Memory Buffer 的内容写入到 Filesystem Cache 的一个新的 segment,然后清空 Memory Buffer 的内容。这个新 segment 是 uncommited 状态,这时候数据可以被搜索到,但是还没有被持久化。
    1. notion image
  1. flush 过程:默认经过 30min 或者 Translog 达到一定大小(受 index.translog.flush_threshold_size 控制,默认 512mb),执行一次 flush 操作,先将 Memory Buffer 中所有的数据 refresh 到 Filesystem Cache 的新的 segment 中,然后创建一个新的 commit point(提交点),提交点的作用是将 Filesystem Cache 的所有 segment 落盘,最后删除旧的 Translog 并创建一个新的 Translog 日志文件。此时数据已经被持久化。
    1. notion image
  1. merge 过程:由于自动刷新流程每秒会创建一个新的 segment ,这样会导致短时间内的 segment 数量暴增。而 segment 数目太多会增加系统资源消耗。es 会在后台进行 merge 操作,小的 segment 被合并到大的 segment,然后这些大的 segment 再合并到更大的 segment。这就是段合并机制。
    1. notion image

3.2 控制近实时行为

  1. 手动刷新
    1. 设置刷新间隔,太短的刷新间隔会增加性能开销。
      1. 禁用自动刷新,适合批量导入场景。
        Zookeeper系列:Zookeeper简介Elasticsearch系列:集群管理
        Loading...