type
status
date
slug
summary
tags
category
icon
password

1、文档是什么

Elasticsearch 中的文档类似数据库的一条数据记录,Elasticsearch 使用 JSON 作为文档的序列化格式。获取文档数据使用下面的代码
可以看到返回的文档里面包含很多元数据:
  • _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 数据。

2、文档的处理过程

1.1 写入/索引文档的流程

当我们执行下面语句新增文档的时候,就会执行文档的写入/索引过程,有两种方式:
写入/索引文档的整个过程如下所示:
notion image
  1. Client 将请求发送到任意节点 node,此时 node 节点就是协调节点(coordinating node)。
  1. 协调节点根据以下计算公式获取目标分片: shard_num = hash(routing) % num_primary_shards ,routing 默认是文档的 id
  1. 得到的目标分片是 primary shard,然后查找到 primary shard 所在的 node,向 primary shard 写入数据。
  1. 然后找到 replica shard 所在的node,向所有 replica shard 同步写入数据。
  1. 最后向协调节点返回写入成功的响应,协调节点再向 Client 返回成功响应。

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
第一阶段:目标是查询到匹配的文档 id。
  1. Client 将请求发送到任意节点 node,此时 node 节点就是协调节点(coordinating node)。
  1. 协调节点进行分词等操作后,去查询所有的 shard ,每个 shard 使用轮询算法在 primary shard 和 replica shard 选择一个。
  1. 所有 shard 将满足条件的数据(文档 id、排序字段等)信息返回给路由节点。
第二阶段,再查询文档 id 对应的完整文档,这一阶段类似于文档的查找过程。
  1. 路由节点重新进行排序,截取数据后,获取到真正需要返回的文档 id。
  1. 根据文档 id 再次请求对应的 shard,获取文档返回协调节点。
  1. 协调节点向 Client 返回数据。

1.4 更新/删除文档的流程

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

3、近实时搜索机制

上面我们简单介绍了文档从写入到搜索的过程,当然这个过程没这么简单。Elasticsearch 是一个近实时搜索(Near real-time search)的搜索引擎。它不像关系型数据库一样,通过事务和隔离性来控制数据的可见,执行数据插入以后立刻就能搜索到刚刚插入的数据。
向 Elasticsearch 插入文档后,默认会要等 1s 后才能搜索到插入的文档,这就是近实时搜索的含义。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 的数据。
数据的整个写入过程如下所示:
notion image
数据落盘完整过程是 write -> refresh -> flush -> merge

3.1 write过程

notion image
写入 Memory Buffer 的,同时写入 Translog,这时候数据还不能被搜索到。Translog 也是先写入 Filesystem Cache,然后默认每隔 5 秒刷一次到磁盘中,所以默认情况下,可能有 5 秒的数据会仅仅停留在 Memory Buffer 或者 Translog 文件的 Filesystem Cache中,而不在磁盘上,如果此时机器宕机,会丢失 5 秒钟的数据。

3.2 refresh过程

notion image
每隔一段时间时间(由 index.refresh_interval 控制,默认1s),执行一次 refresh 操作,将所有 Memory Buffer 的内容写入到 Filesystem Cache 的一个新的 segment,然后清空 Memory Buffer 的内容。这个新 segment 是 uncommited 状态,这时候数据可以被搜索到,但是还没有被持久化。

3.3 commit过程

notion image
默认经过 30min 或者 Translog 达到一定大小(受 index.translog.flush_threshold_size 控制,默认 512mb),执行一次 flush 操作,先将 Memory Buffer 中所有的数据 refresh 到 Filesystem Cache 的新的 segment 中,然后创建一个新的 commit point(提交点),将 Filesystem Cache 的所有 segment 落盘,最后删除旧的 Translog 并创建一个新的 Translog 日志文件。此时数据已经被持久化。

3.4 merge过程

notion image
由于自动刷新流程每秒会创建一个新的 segment ,这样会导致短时间内的 segment 数量暴增。而 segment 数目太多会增加系统资源消耗。es 会在后台进行 merge 操作,小的 segment 被合并到大的 segment,然后这些大的 segment 再合并到更大的 segment。这就是段合并机制。
Kibana的搜索语法Elasticsearch系列:索引模板
mcbilla
mcbilla
一个普通的干饭人🍚
Announcement
type
status
date
slug
summary
tags
category
icon
password
🎉欢迎来到飙戈的博客🎉
-- 感谢您的支持 ---
👏欢迎学习交流👏