Elasticsearch 参考指南(读和写文档)

读和写文档

本节简要介绍Elasticsearch的数据复制模型。html

介绍

Elasticsearch中的每一个索引都分为碎片,每一个碎片能够有多个副本,这些副本称为复制组,在添加或删除文档时必须保持同步。若是咱们不这样作,从一个副本中读取将致使与从另外一个副本读取的结果大相径庭,保持碎片副本同步并从中提供读取的过程就是咱们所说的数据复制模型。git

Elasticsearch的数据复制模型基于主备模型,并在微软研究院的PacificA paper论文中获得了很好的描述。该模型基于从复制组中持有一个副本做为主碎片,其余副本称为副本碎片。主碎片服务做为全部索引操做的主要入口点,它负责验证它们并确保它们是正确的,一旦主碎片接受了索引操做,主碎片负责将操做复制到其余副本。github

本节的目的是对Elasticsearch复制模型做一个高层次的概述,并讨论它对读和写操做之间的各类交互的影响。segmentfault

基础写模型

Elasticsearch中的每一个索引操做首先使用路由解析为一个复制组,一般基于文档ID,一旦肯定了复制组,操做将在内部转发到当前组的主碎片,主碎片负责验证操做并将其转发到其余副本。因为副本能够脱机,主碎片不须要复制到全部副本,相反,Elasticsearch维护一个应该收到操做的碎片副本列表,这个列表称为同步副本,由主节点维护。顾名思义,这些是一组“好的”碎片副本,它们保证已经处理了已向用户确认的全部索引和删除操做,主碎片负责维护这个不变量,所以必须将全部操做复制到这个集合中的每一个副本。网络

主碎片遵循这个基本流程:并发

  1. 验证传入的操做并在结构上无效时拒绝它(例如:有一个对象字段,其中一个数字是预期的)。
  2. 在本地执行操做,即索引或删除相关文档,这还将验证字段的内容并在必要时拒绝(例如:在Lucene中用于索引的一个关键字太长)。
  3. 将操做转发到当前同步副本集合中的每一个副本,若是有多个副本,则并行执行。
  4. 一旦全部副本都成功地执行了操做并响应了主碎片,主碎片就会对客户端确认请求已经成功完成。

故障处理

在索引过程当中,许多事情均可能出错 - 磁盘可能会损坏、节点之间可能断开链接、或某些配置错误可能致使副本上的操做失败,尽管它在主碎片上是成功的,这种状况并不常见,但主碎片必须对其做出响应。elasticsearch

在主碎片失败的状况下,主碎片所在的节点将向主节点发送关于主碎片失败的消息,索引操做将等待(默认状况下最多1分钟),以便主节点将一个副本提高为一个新的主碎片。而后,操做将被转发到新的主碎片进行处理,注意,主节点还监控节点的健康情况,并可能决定主动降级主碎片,这一般发生在持有主碎片的节点因为网络问题与集群隔离时。ide

在主碎片上成功执行操做以后,当在副本碎片上执行操做时,主碎片必须处理潜在的故障,这多是因为副本上的实际故障,或者是因为网络问题阻止操做到达副本(或者阻止副本响应)。全部这些都有相同的最终结果:同步副本集合中的一个副本错过一个将要被确认的操做,为了不违反不变量,主碎片向主节点发送一条消息,请求从同步副本集合中删除有问题的碎片。只有在主节点确认移除碎片后,主碎片才会确认操做,注意,主节点还将指示另外一个节点开始构建一个新的碎片副本,以便将系统恢复到健康状态。网站

在将操做转发到副本时,主碎片将使用副原本验证它仍然是活动的主碎片,若是主碎片因为网络分区(或长时间GC)而被隔离,在乎识到主碎片已经被降级以前它可能会继续处理传入的索引操做,来自过时的主碎片的操做将被副本拒绝。当主碎片收到来自副本的拒绝它请求的响应,由于它再也不是主碎片时,它会联系主节点,并将会知道它已经被替换了,而后将操做路由到新的主碎片。ui

若是没有副本会发生什么?

这是一个因为索引配置或仅仅由于全部副本都失败而可能发生的有效场景,在这种状况下,主碎片是在没有任何外部验证的状况下处理操做,这可能看起来有问题,另外一方面,主碎片自己不能使其余碎片失败,但请求主节点表明它这样作,这意味着主节点知道主碎片是惟一一个好的副本。所以,咱们保证主节点不会将任何其余(过时的)碎片副本提高为新的主碎片,而且主碎片中索引的任何操做都不会丢失,固然,由于此时咱们只运行数据的一个副本,因此物理硬件问题可能致使数据丢失。

基础读模型

在Elasticsearch中的读能够是很是轻量的经过ID的查找,也能够是使用复杂聚合的繁重搜索请求,而复杂的聚合会占用大量的CPU资源。主备模型的优势之一是保持全部碎片副本相同(除了飞行的操做以外),所以,一个同步副本就足以服务于读请求。

当节点接收到读请求时,该节点负责将其转发到持有相关碎片的节点、整理响应并响应客户端,咱们将该节点称为该请求的协调节点,基本流程以下:

  1. 将读请求解析到相关的碎片,注意,因为大多数搜索将被发送到一个或多个索引,它们一般须要从多个碎片中读,每一个碎片表明数据的不一样子集。
  2. 从碎片复制组中选择每一个相关碎片的活动副本,这能够是主碎片,也能够是副本,默认状况下,Elasticsearch将会在碎片副本之间进行简单的循环负载。
  3. 将碎片级别的读请求发送到选中的副本。
  4. 组合结果和响应,注意,在get by ID查找的状况下,只有一个碎片是相关的,能够跳过这一步。

故障处理

当碎片没法响应读请求时,协调节点将从同一复制组中选择另外一个副本,并将碎片级搜索请求发送到该副本,重复的失败会致使碎片副本不可用。在某些状况下,好比_search,Elasticsearch将更喜欢快速响应,尽管会获得部分结果,而不是等待问题获得解决(响应的_shards头中显示了部分结果)。

几个简单的含义

这些基础流中的每个都决定了Elasticsearch做为读写系统的行为,此外,因为读写请求能够并发执行,这两个基本流相互交互,这有一些内在的含义:

高效的读

  • 在正常操做下,对每一个相关复制组执行一次读操做,只有在失败的状况下,同一个碎片的多个副本才会执行相同的搜索。

未确认的读

  • 因为主碎片首先本地索引,而后复制请求,因此并发读可能在确认更改以前就已经看到了更改。

默认为两个副本

  • 这个模型能够在当只维护数据的两个副本时容错,这与基于数量的系统造成对比,其容错的最小副本数为3。

故障

在故障的状况下,如下是可能的状况:

单个碎片能够减慢索引速度

  • 由于主碎片在每次操做期间都要等待同步复制集中的全部副本,因此单个慢碎片可能会减慢整个复制组的速度,这是咱们为上述读效率所付出的代价,固然,单个慢碎片也会不幸的减慢被路由到它的搜索。

脏读

孤立的主碎片能够公开不被认可的写操做,这是由这样一个事实引发的:一个孤立的主碎片只有在向其副本发送请求或与主节点接触时才会意识到它是孤立的,这时,操做已经被索引到主碎片中,而且能够被并发读取,Elasticsearch经过每秒ping一次主节点(默认状况下)并在若是不知道主节点的状况下拒绝索引操做来减轻这种风险。

冰山一角

本文档提供了Elasticsearch如何处理数据的高层次概述,固然,在引擎下还有不少事情要作,像主碎片项、集群状态发布和主节点选举等都在保持系统正常运行方面发挥了做用,本文档也没有已知的和重要的bug(关闭和打开),咱们认识到Github很难跟上,为了帮助人们保持在这些之上,咱们在咱们的网站上维护一个专用的弹性页面,咱们强烈建议你阅读它。


下一篇:Index API

相关文章
相关标签/搜索