读写文档

介绍

Elasticsearch中的每个索引都进行 分片,每个分片可能有多个副本。这些副本称为副本组,在添加或删除文档时必须保持同步。如果我们不这样做,从两个不同副本中读取的结果可能截然不同。保持分片副本同步并提供读取的过程,就是我们所说的数据复制模型。

Elasticsearch的数据复制模型基于主备份模型,并在Microsoft Reseach的 PacificA论文 中进行了很好的描述。该模型中,副本组的一个副本作为主分片,其他副本称为副本分片。主分片作为所有索引操作的主要入口点。它负责验证其他副本分片,并确保它们是正确的。一旦主分片接受了索引操作,负责将操作复制到其他副本。

本节的目的是对Elasticsearch复制模型进行高级概述,并讨论它对读写操作等各种交互的影响。

基本写模型

Elasticsearch中的每个索引操作首先使用 路由 解析为副本组,通常基于文档ID。确定副本组后,操作将在内部转发到副本组的主分片。主分片负责验证操作并将其转发到其他副本。由于副本可以脱机,因此不是必须将主副本复制到所有副本。相反,Elasticsearch维护应该接收操作的分片副本列表。此列表称为同步副本,由主节点维护。顾名思义,这些是“好”分片副本的集合,在反馈用户时,会确保已经处理了所有索引和删除操作。主分片负责维护此不变量,因此必须将所有操作复制到此集合中的每个副本。

主分片遵循以下基本流程:

  1. 验证传入操作,并在结构无效时拒绝它(例如:有一个对象字段,其中包含一个数字)
  2. 执行本地操作,即索引或删除相关文档。这也将验证字段的内容,并在需要时拒绝操作(例如:关键字值太长,无法在Lucene中进行索引)。
  3. 将操作转发到当前同步副本集中的每个副本。如果有多个副本,则这是并行完成的。
  4. 一旦所有副本成功执行了操作,并响应主服务器,主服务器就会向客户端确认成功完成请求。

失败处理

在索引编制过程中可能会出现许多问题——磁盘可能会损坏,节点可能会相互断开连接,或者某些配置错误可能导致复制副本的操作失败,尽管它在主服务器上成功。这些很少见,但主要必须响应它们。

在主分片身发生故障的情况下,托管主分片的节点将向主服务器发送有关它的消息。索引操作将等待(默认情况下最多1分钟),以便主服务器将其中一个副本提升为新的主分片。然后,该操作将被转发到新的主分片。请注意,主服务器还会监控节点的运行状况,并可能决定主动降级主服务器。当主分片所在节点因网络问题与集群隔离时,通常会发生这种情况。

一旦在主分片上成功执行了操作,主分片在副本分片执行操作时,必须处理潜在的故障。这可能是由副本上的故障导致,或因网络问题导致操作无法到达副本(或阻止副本响应)。所有这些都具有相同的最终结果:作为同步副本集的一部分的副本错过了即将被确认的操作。为了避免与不变量有差异,主分片向主服务器发送消息,请求从同步副本集中删除有问题的分片。只有在主节点确认删除了碎片后,主分片才会确认操作。请注意,主节点还将指示另一个节点开始构建新的分片副本,以便将系统恢复到正常状态。

在将操作转发到副本时,主分片将使用副本来验证自身仍然是活动主分片。如果主分片由于网络分区(或长GC)而被隔离,则它可能会在意识到它已被降级之前,继续处理传入的索引操作。来自旧的主分片的操作将被其余分片拒绝。当主分片收到其他副本拒绝其请求的响应时,因为它不再是主分片,那么它将联系主服务器并将知道它已被替换,然后将操作路由到新主分片。

如果没有副本会怎么样?

这个情况是有可能出现的,当索引配置或所有副本都失效时发生。在这种情况下,主分片会进行操作,而没有任何外部验证,这看起来可能会有问题。另一方面,主分片本身不能使其他分片失效,但可以请求主节点代表它执行此操作。这意味着主节点知道主分片是唯一的良好副本。因此,我们可以保证主服务器不会将任何其他(过时的)分片副本提升为新主分片,并且任何索引到主分片的操作都不会丢失。当然,由于此时我们只使用单个数据副本运行,因此物理硬件问题可能会导致数据丢失。请参阅 等待活动分片 以获取一些解决办法。

基本读模型

Elasticsearch中的读取是非常轻量级的通过ID查找,也可以是大量复杂搜索请求的聚合的,这些聚合会占用大量CPU性能。主-备模型的一个优点是,它使所有分片副本保持相同(除了正在进行的操作)。因此,单个同步副本足以提供读取请求。

当节点收到读取请求时,该节点负责将其转发到保存相关分片的节点,核对响应并响应客户端。我们将此节点称为该请求的协调节点。基本流程如下:

  1. 将读取请求解析到相关分片。请注意,由于大多数搜索将被发送到一个或多个索引,因此它们通常需要从多个分片中读取,每个分片代表数据的不同子集。
  2. 从分片副本组中选择每个相关分片的活动副本。这可以是主分片或副本分片。默认情况下,Elasticsearch将简单地在副本分片之间循环。
  3. 将分片级读取请求发送到所选副本。
  4. 整合结果并做出响应。请注意,在通过ID查找的情况下,只与一个分片相关,可以跳过此步骤。

失败处理

当分片无法响应读取请求时,协调节点将从同一副本组中选择另一副本,并将分片级别搜索请求发送到该副本。重试失败可能导致没有可用的分片副本。

为确保快速响应,如果一个或多个分片失败,以下API将响应部分结果:

包含部分结果的响应仍提供200 OKHTTP状态代码。 碎片失败由响应头的timed_out_shards字段指示。

一些简单的含义

每一个基本流程都决定了Elasticsearch系统如何读取和写入。此外,由于读取和写入请求可以同时执行,因此这两个基本流程彼此交互。这有一些固有的含义:

高效读取

​ 在正常操作下,对每个相关副本组执行一次读取操作。只有在失败条件下,同一个分片的多个副本才会执行相同的搜索。

阅读未经承认

​ 由于主分片首先在本地索引,然后复制请求,因此并发读取可能在确认之前已经看到了更改。

默认两副本

​ 此模型仅需维护两个数据副本就可具备容错性。这与基于法定数量的系统(容错的最小副本数为3)不同。

失败

在失败的情况下,以下是可能的:

单个分片减慢索引速度

​ 由于主分片在每个操作期间,等待同步副本集中的所有副本,因此某个慢速分片可能会降低整个副本组的速度。这是我们为上述阅读效率产生的成本。当然,当查询不幸路由到单个慢速分片时,也会减慢速度。

脏读

​ 隔离的主分片可以暴露无法识别的写入。这是因为隔离的主分片只有在向其副本发送请求,或向主服务器发送请求时才会意识到它是隔离的。此时,操作已经索引到主分片中,并且可以进行并发读取。 Elasticsearch通过每秒ping一次(默认情况下)主节点,从而在找不到主节点的情况下拒绝索引操作,以此来降低风险。

冰山一角的提示

本文档提供了Elasticsearch如何处理数据的高级概述。当然,还有很多事情发生。例如主术语、集群状态发布和主选举等,都在保持系统正常运行方面发挥作用。本文档也未涵盖已知和重要的错误(关闭和打开)。我们认识到 GitHub 很难跟上。为了帮助人们掌控这些,我们在我们的网站上维护了一个专用的 弹性页面。我们强烈建议阅读它。

results matching ""

    No results matching ""