文档如何进入集群
Elasticsearch® 是一个非常强大和灵活的分布式数据系统,可以接受和索引数十亿个文档,使它们可以近乎实时地用于搜索、聚合和分析。本文是关于如何完成的,重点介绍基本的新数据插入以及从请求一直到磁盘的数据流。
索引是一个相对简单的高级过程,包括:
- 通过 API 到达数据
- 路由到正确的索引、分片和节点
- 映射、规范化和分析
- 存储在内存和磁盘上
- 使其可用于搜索
然而,实际过程要复杂得多,尤其是考虑到集群及其数据的分布式特性、所涉及的高数据速率以及同时进行的所有操作的并行特性。此外,这一切都必须尽可能可靠和可扩展。这就是 Elasticsearch 的魔力。
让我们更详细地看一下这些步骤。
到货与分批
Elasticsearch 首先通过索引 API 了解传入数据以进行索引。Logstash、Beats 甚至 cURL 等客户端将数据发送到集群的节点进行处理。他们一次可以发送一个文档,但通常使用批量 API 批量发送数据,以减少开销并加快处理速度。批次只是在一次 API 调用中发送的一组文档,不需要相关,即它们可以包含发往多个不同索引的数据。
摄取数据可以发送到任何节点。然而,较大的集群通常使用专用的协调节点(更多用于搜索而不是摄取),甚至是专用的摄取节点,它们可以运行数据管道来预处理数据。数据到达的任何节点都将成为该批次的协调节点,并将数据路由到正确的位置,即使实际的摄取工作是在保存目标索引数据的数据节点上执行的。
管道和数据流
数据最常到达单个标准索引,但也可以路由到数据流或摄取管道。数据流是 X-Pack 的一项功能,通常用于处理时间序列数据,例如指标和日志,并且本质上解析为这个摄取过程的实际支持索引。管道是一组处理器,用于在文档数据被索引之前对其进行操作。
如果请求或批处理包含管道并且协调节点也不是摄取节点,那么它似乎会首先被路由到摄取节点,然后继续到主节点。不清楚是协调节点还是摄取节点将其发送到主节点,但可能是协调节点,即摄取节点,运行管道,然后将文档返回到协调节点以进行下一步。
路由
一旦数据到达协调节点,必须将每个文档路由到正确的索引、分片和节点以进行摄取。由于批量请求可能包含许多索引的数据,并且单个索引的多个文档可能会转到单独的分片,因此路由步骤是针对每个文档运行的,并且对于将每个文档放到正确的位置非常重要。这个过程开始了“协调阶段”。
每个文档的第一步是协调节点使用提供的索引、别名、数据流等来确定文档将要到达的实际目标索引。如果索引不存在,则会创建它,然后该过程可以继续。请注意,Elasticsearch 会先尝试创建批量请求所需的所有索引,然后再进行任何索引。
在协调节点知道目标索引后,它会运行一个路由过程来为文档选择索引的分片。路由可能会变得复杂,默认情况下由文档 ID 驱动,默认情况下由协调节点自动生成。
如果您愿意,客户端可以指定自己的 ID,还可以控制用于路由的字段,例如时间戳、用户、源设备等,作为集群策略,将相关(并且可快速查询)数据共同定位在单个分片。此外,索引可以具有将文档强制到特定分片的自定义路由。但通常,每个文档将随机分布在其目标索引的分片中。
路由过程的结果将是目标分片及其分片 ID,但我们必须记住,分片可能有副本。如果有副本,协调节点也会将它们包含在路由列表中,因此结果是该文档所有分片的列表:主分片和副本。然后,协调节点查找这些分片的节点 ID,以了解将文档路由到何处以进行索引。
索引阶段
一旦协调节点知道文档的目标主分片和该分片的节点,文档就会被发送到该节点进行主索引,作为“主阶段”的一部分。主分片验证请求,然后在本地索引它们,这也验证映射、字段等。该过程将在下面更详细地描述。
如果主节点索引成功,则主分片节点(不是协调节点)将文档并行发送到所有“同步”“活动”副本,即“副本阶段”。主分片节点等待所有副本完成索引,然后将结果返回给等待的协调节点。一旦批处理中的所有文档都被索引(或失败),协调器然后将结果返回给原始 API 调用者,即客户端。
每个文档都由其每个
主分片和副本分片单独索引。
必须了解每个文档都由它将存在的每个分片单独索引,并且所有这些都必须在给定文档被“索引”之前完成。因此,如果一个索引的副本数为 3,这意味着每个文档都将转到四个分片(主分片和三个副本),并分别被四个分片(主分片和三个副本)索引,所有分片都位于不同的节点上。
Elasticsearch 中没有真正的预处理或中央索引,集群完成的“工作”随着给定索引的副本数量线性增加。这通常是大多数索引延迟发生的地方,因为它只能与最慢的节点和分片一样慢。
协调器节点尽可能多地并行处理一批文档。它将文档并行发送到其路由的主分片,但似乎每个主分片仅对一个请求进行排队。因此,如果批次有 10 个文档用于单个索引和单个分片,这些将全部按顺序处理,一次一个,但如果批次有 10 个文档用于两个索引,每个索引有 5 个分片,并且路由结果为一个每个分片的文档,所有 10 个将并行完成。这是附加主分片加快处理速度的一种方式。
分片级索引
一旦文档到达拥有它所在的分片的给定节点,实际的文档索引就完成了。第一步是将文档写入 translog 以获得持久副本,以防在此之后发生节点崩溃。
translog 是 Elasticsearch 的一项功能,它提供的持久性超出了 Lucene 自己可以做到的程度,并且是可靠系统的关键。如果节点在实际索引完成之前崩溃,则在重新启动时,Elasticsearch 会将文档重播到索引进程中,以确保它得到处理。
实际的索引过程有几个步骤:
- 在 Elasticsearch 中映射文档字段
- 在 Lucene 中分析
- 添加到Lucene中的倒排索引
首先,节点通过索引的模板映射文档的字段,该模板指定如何处理每个字段,例如类型,还包括分析器和其他选项。由于每个文档都可以有不同的字段和数据,所以这个映射步骤是必不可少的,也是经常发生错误的地方,因为字段类型不匹配、超出范围等。这项工作是在 Elasticsearch 级别完成的,因为 Lucene 有没有模板或地图的概念。一个 Lucene 文档只是一组字段,每个字段都有一个名称、类型和一个值。
其次,文档被传递给 Lucene,后者将对其进行“分析”。在实践中,这意味着在其上运行配置的分析器,每个分析器可以有几个步骤和组件,包括标记和过滤,它们一起可以做很多强大的事情。
标记化将每个字段中的数据拆分为标记,例如在空格上分隔单词,过滤包括除基本过滤之外的广泛内容,小写文本,删除停用词和通过词干进行标准化(即更改单词到他们的“正常”版本,例如狗变成狗,看着变成手表,等等)
最后,Lucene 获取结果并为此文档建立存储记录。这通常包括文档中的每个字段,以及可用于重新索引等的特殊字段,例如 _source 和 _all,以及最重要的倒排索引本身。
Lucene 将所有这些写入内存中的段缓冲区,然后成功返回协调节点。一旦在所有副本分片上完成此操作,从协调节点或客户端的角度来看,该文档的索引基本上是完整的。
获取磁盘上的文档数据并可搜索
刚刚索引的文档仅在内存中的临时多文档段中,尚未在磁盘上,也无法用于搜索。两个独立的进程在幕后运行,以使这两件事发生。
索引数据尚未在磁盘上,也无法搜索。
第一个过程是“刷新”以使数据可用于搜索。刷新间隔是按索引设置的,默认为 1 秒。许多用户将此设置得更高,例如 30-60 秒,因为这是一项昂贵的操作,并且每秒执行一次会降低整体索引吞吐量。请注意,不经常搜索的索引在被搜索之前不会自动刷新,以提高批量索引速度。
在刷新间隔,内存缓冲区的段被合并并写入文件系统上的单个新段,并且数据可用于搜索。但是,虽然这个段现在存在于文件系统中,但它主要在文件缓存中,可能实际上并不在磁盘上,如果此时发生崩溃,这是一个问题。数据可用,但不安全,但如果发生崩溃,translog 仍然存在并会被播放,并且会再次对文档进行索引。
为了使数据在磁盘上安全,有一个单独的 Elasticsearch 刷新过程执行 Lucene 提交,它合并和 fsync 上述段,确保它们确实在磁盘上。完成后,Elasticsearch 会截断 translog,因为数据现在安全地保存在磁盘上,不会在崩溃中丢失。Elasticsearch 根据 translog 大小(默认最大值为 512MB)安排这些刷新,以帮助保持合理的恢复时间。
本质上,translog 维护所有新文档更改的可靠性,以及 Elasticsearch 刷新/Lucene 提交之间的可靠性。请注意,translog 有自己的可靠性设置,包括每 5 秒 fsync 到磁盘的默认设置。
Elasticsearch 还单独运行后台线程以尽可能地继续合并段,使用分层合并策略来尽量减少段数(因为它们是按顺序搜索的),同时不会降低整体实时索引和搜索性能。这与上述所有过程是分开的。
总体结果是,在任何给定时间,任何特定的可用索引都由磁盘上的一组不同大小的永久段和文件缓存中的一些新段组成。加上仅在内存中的索引但尚不可用的段,等待刷新间隔。
问题
Elasticsearch 索引是一个非常好的但复杂的分布式过程,它平衡了高性能、数据可靠性和强大的功能。虽然它运作良好,但事情可能而且确实会出错。有些问题出在文档本身,而其他问题则出在集群方面。
集群级别的问题通常与过程中的分片丢失或移动有关。正常流程是从协调节点到主节点再到副本节点,但是如果主节点在此过程中发生变化,或者副本丢失,会发生什么情况?有各种复杂的重试、超时和路由过程会尝试保存文档,当然,它们可能会失败,此时客户端必须重试。
其中一些,例如副本超时或失败,将导致该分片被声明为不同步和无效,将索引状态更改为黄色并安排副本重建。其他的,比如网络分区,会导致主节点本身被声明为无效,当它尝试与副本通信时会发现这一点。总的来说,这是一个复杂但强大的系统。
参考
有几篇关于这个过程的好文章,但大多数都是很多年的,最好的文章涵盖了 Elasticsearch 的早期版本,尽管过程大致相同:
关于埃尔克曼
ELKman 是我们的 ELK Stack 管理工具,可帮助您管理、调整、审计和优化您的 Elasticsearch 系统,包括查看上述流程的实际运行情况。更多在ELKMan.io
转载:https://medium.com/swlh/elasticsearch-indexing-data-flow-d56ea14e1772