Elasticsearch从入门到精通之Elasticsearch集群内的原理

上一章节我介绍了Elasticsearch安装与运行,本章节及后续章节将全方位介绍 Elasticsearch 的工做原理

在这个章节中,我将会再进一步介绍 cluster 、 node 、 shard 等经常使用术语,Elastisearch 的扩容机制, 以及如何处理硬件故障的内容。html

一、分布式特性

Elasticsearch 能够横向扩展至数百(甚至数千)的服务器节点,同时能够处理PB级数据。Elasticsearch 天生就是分布式的,而且在设计时屏蔽了分布式的复杂性。node

Elasticsearch 在分布式方面几乎是透明的。教程中并不要求了解分布式系统、分片、集群发现或其余的各类分布式概念。可使用笔记本上的单节点轻松地运行教程里的程序,但若是你想要在 100 个节点的集群上运行程序,一切依然顺畅。git

Elasticsearch 尽量地屏蔽了分布式系统的复杂性。这里列举了一些在后台自动执行的操做:github

  • 分配文档到不一样的容器 或 分片 中,文档能够储存在一个或多个节点中
  • 按集群节点来均衡分配这些分片,从而对索引和搜索过程进行负载均衡
  • 复制每一个分片以支持数据冗余,从而防止硬件故障致使的数据丢失
  • 将集群中任一节点的请求路由到存有相关数据的节点
  • 集群扩容时无缝整合新节点,从新分配分片以便从离群节点恢复

二、集群原理

ElasticSearch 的主旨是随时可用和按需扩容。 而扩容能够经过购买性能更强大( 垂直扩容 ,或 纵向扩容)  或者数量更多的服务器( 水平扩容 ,或 横向扩容 )来实现。数据库

虽然 Elasticsearch 能够获益于更强大的硬件设备,可是垂直扩容是有极限的。 真正的扩容能力是来自于水平扩容--为集群添加更多的节点,而且将负载压力和稳定性分散到这些节点中。json

对于大多数的数据库而言,一般须要对应用程序进行很是大的改动,才能利用上横向扩容的新增资源。 与之相反的是,ElastiSearch天生就是 分布式的 ,它知道如何经过管理多节点来提升扩容性和可用性。 这也意味着你的应用无需关注这个问题。服务器

2.一、空集群

若是咱们启动了一个单独的节点,里面不包含任何的数据和 索引,那咱们的集群看起来就像下图1同样。app

图 1. 包含空内容节点的集群负载均衡

包含空内容节点的集群

 

一个运行中的 Elasticsearch 实例称为一个 节点,而集群是由一个或者多个拥有相同 cluster.name 配置的节点组成, 它们共同承担数据和负载的压力。当有节点加入集群中或者从集群中移除节点时,集群将会从新平均分布全部的数据。curl

当一个节点被选举成为  节点时, 它将负责管理集群范围内的全部变动,例如增长、删除索引,或者增长、删除节点等。 而主节点并不须要涉及到文档级别的变动和搜索等操做,因此当集群只拥有一个主节点的状况下,即便流量的增长它也不会成为瓶颈。 任何节点均可以成为主节点。咱们的示例集群就只有一个节点,因此它同时也成为了主节点。

做为用户,咱们能够将请求发送到 集群中的任何节点 ,包括主节点。 每一个节点都知道任意文档所处的位置,而且可以将咱们的请求直接转发到存储咱们所需文档的节点。 不管咱们将请求发送到哪一个节点,它都能负责从各个包含咱们所需文档的节点收集回数据,并将最终结果返回給客户端。 Elasticsearch 对这一切的管理都是透明的。

2.二、集群健康

lasticsearch 的集群监控信息中包含了许多的统计数据,其中最为重要的一项就是 集群健康 , 它在 status 字段中展现为 green 、 yellow 或者 red 。

GET /_cluster/health
 

在一个不包含任何索引的空集群中,它将会有一个相似于以下所示的返回内容:

{
   "cluster_name":          "elasticsearch",
   "status":                "green", 
   "timed_out":             false,
   "number_of_nodes":       1,
   "number_of_data_nodes":  1,
   "active_primary_shards": 0,
   "active_shards":         0,
   "relocating_shards":     0,
   "initializing_shards":   0,
   "unassigned_shards":     0
}
 

status 字段指示着当前集群在整体上是否工做正常。它的三种颜色含义以下:

green
全部的主分片和副本分片都正常运行。
yellow
全部的主分片都正常运行,但不是全部的副本分片都正常运行。
red
有主分片没能正常运行。

 

2.三、新增索引

咱们往 Elasticsearch 添加数据时须要用到索引 —— 保存相关数据的地方。 索引其实是指向一个或者多个物理分片 的逻辑命名空间 。

一个分片 是一个底层的工做单元 ,它仅保存了 所有数据中的一部分。 在分片内部机制中,咱们将详细介绍分片是如何工做的,而如今咱们只需知道一个分片是一个 Lucene 的实例,以及它自己就是一个完整的搜索引擎文件。 咱们的文档被存储和索引到分片内,可是应用程序是直接与索引而不是与分片进行交互。

Elasticsearch 是利用分片将数据分发到集群内各处的。分片是数据的容器,文档保存在分片内,分片又被分配到集群内的各个节点里。 当你的集群规模扩大或者缩小时, Elasticsearch 会自动的在各节点中迁移分片,使得数据仍然均匀分布在集群里。

一个分片能够是  分片或者 副本 分片。 索引内任意一个文档都归属于一个主分片,因此主分片的数目决定着索引可以保存的最大数据量。

注意

技术上来讲,一个主分片最大可以存储 Integer.MAX_VALUE - 128 个文档,可是实际最大值还须要参考你的使用场景:包括你使用的硬件, 文档的大小和复杂程度,索引和查询文档的方式以及你指望的响应时长。

一个副本分片只是一个主分片的拷贝。 副本分片做为硬件故障时保护数据不丢失的冗余备份,并为搜索和返回文档等读操做提供服务。

在索引创建的时候就已经肯定了主分片数,可是副本分片数能够随时修改。

让咱们在包含一个空节点的集群内建立名为 shops 的索引。 索引在默认状况下会被分配5个主分片, 可是为了演示目的,咱们将分配3个主分片和一份副本(每一个主分片拥有一个副本分片):

PUT /shops 
{
   "settings" : {
      "number_of_shards" : 3,
      "number_of_replicas" : 1
   }
}
 

咱们的集群如今是图 2 “拥有一个索引的单节点集群”。全部3个主分片都被分配在 Node 1 。

图 2. 拥有一个索引的单节点集群

拥有一个索引的单节点集群

 

若是咱们如今查看集群健康 咱们将看到以下内容:

{
  "cluster_name": "elasticsearch",
  "status": "yellow", 
  "timed_out": false,
  "number_of_nodes": 1,
  "number_of_data_nodes": 1,
  "active_primary_shards": 3,
  "active_shards": 3,
  "relocating_shards": 0,
  "initializing_shards": 0,
  "unassigned_shards": 3, 
  "delayed_unassigned_shards": 0,
  "number_of_pending_tasks": 0,
  "number_of_in_flight_fetch": 0,
  "task_max_waiting_in_queue_millis": 0,
  "active_shards_percent_as_number": 50
}

集群 status 值为 yellow 。

没有被分配到任何节点的副本数。

集群的健康情况为 yellow 则表示所有 分片都正常运行(集群能够正常服务全部请求),可是副本 分片没有所有处在正常状态。 实际上,全部3个副本分片都是 unassigned —— 它们都没有被分配到任何节点。 在同一个节点上既保存原始数据又保存副本是没有意义的,由于一旦失去了那个节点,咱们也将丢失该节点上的全部副本数据。

当前咱们的集群是正常运行的,可是在硬件故障时有丢失数据的风险。

2.四、故障转移

当集群中只有一个节点在运行时,意味着会有一个单点故障问题——没有冗余。 幸运的是,咱们只需再启动一个节点便可防止数据丢失。

若是启动了第二个节点,咱们的集群将会如图 3 “拥有两个节点的集群——全部主分片和副本分片都已被分配”所示。

图 3. 拥有两个节点的集群——全部主分片和副本分片都已被分配

拥有两个节点的集群

 

当第二个节点加入到集群后,3个 副本分片 将会分配到这个节点上——每一个主分片对应一个副本分片。 这意味着当集群内任何一个节点出现问题时,咱们的数据都无缺无损。

全部新近被索引的文档都将会保存在主分片上,而后被并行的复制到对应的副本分片上。这就保证了咱们既能够从主分片又能够从副本分片上得到文档。

cluster-health 如今展现的状态为 green ,这表示全部6个分片(包括3个主分片和3个副本分片)都在正常运行。

{
  "cluster_name": "elasticsearch",
  "status": "green", 
  "timed_out": false,
  "number_of_nodes": 2,
  "number_of_data_nodes": 2,
  "active_primary_shards": 3,
  "active_shards": 6,
  "relocating_shards": 0,
  "initializing_shards": 0,
  "unassigned_shards": 0,
  "delayed_unassigned_shards": 0,
  "number_of_pending_tasks": 0,
  "number_of_in_flight_fetch": 0,
  "task_max_waiting_in_queue_millis": 0,
  "active_shards_percent_as_number": 100
}

集群 status 值为 green 。

咱们的集群如今不只仅是正常运行的,而且还处于 始终可用 的状态。

2.五、水平扩容

怎样为咱们的正在增加中的应用程序按需扩容呢? 当启动了第三个节点,咱们的集群将会看起来如图 4 “拥有三个节点的集群——为了分散负载而对分片进行从新分配”所示。

图 4. 拥有三个节点的集群——为了分散负载而对分片进行从新分配

拥有三个节点的集群

 

Node 1 和 Node 2 上各有一个分片被迁移到了新的 Node 3 节点,如今每一个节点上都拥有2个分片,而不是以前的3个。 这表示每一个节点的硬件资源(CPU, RAM, I/O)将被更少的分片所共享,每一个分片的性能将会获得提高。

分片是一个功能完整的搜索引擎,它拥有使用一个节点上的全部资源的能力。 咱们这个拥有6个分片(3个主分片和3个副本分片)的索引能够最大扩容到6个节点,每一个节点上存在一个分片,而且每一个分片拥有所在节点的所有资源。

2.5.一、更多的扩容

可是若是咱们想要扩容超过6个节点怎么办呢?

主分片的数目在索引建立时 就已经肯定了下来。实际上,这个数目定义了这个索引可以存储 的最大数据量。(实际大小取决于你的数据、硬件和使用场景。) 可是,读操做——搜索和返回数据——能够同时被主分片 副本分片所处理,因此当你拥有越多的副本分片时,也将拥有越高的吞吐量。

在运行中的集群上是能够动态调整副本分片数目的 ,咱们能够按需伸缩集群。让咱们把副本数从默认的 1增长到 2 :

PUT /shops/_settings
{
   "number_of_replicas" : 2
}
 

如图 5 “将参数 number_of_replicas 调大到 2”所示, shops 索引如今拥有9个分片:3个主分片和6个副本分片。 这意味着咱们能够将集群扩容到9个节点,每一个节点上一个分片。相比原来3个节点时,集群搜索性能能够提高 3 倍。

图 5. 将参数 number_of_replicas 调大到 2

拥有2份副本分片3个节点的集群

注意

固然,若是只是在相同节点数目的集群上增长更多的副本分片并不能提升性能,由于每一个分片从节点上得到的资源会变少。 你须要增长更多的硬件资源来提高吞吐量。

可是更多的副本分片数提升了数据冗余量:按照上面的节点配置,咱们能够在失去2个节点的状况下不丢失任何数据。

2.六、应对故障

咱们以前说过 Elasticsearch 能够应对节点故障,接下来让咱们尝试下这个功能。 若是咱们关闭第一个节点,这时集群的状态为图 6 “关闭了一个节点后的集群”

图 6. 关闭了一个节点后的集群

关闭了一个节点后的集群

 

咱们关闭的节点是一个主节点。而集群必须拥有一个主节点来保证正常工做,因此发生的第一件事情就是选举一个新的主节点: Node 2 。

在咱们关闭 Node 1 的同时也失去了主分片 1 和 2 ,而且在缺失主分片的时候索引也不能正常工做。 若是此时来检查集群的情况,咱们看到的状态将会为 red :不是全部主分片都在正常工做。

幸运的是,在其它节点上存在着这两个主分片的完整副本, 因此新的主节点当即将这些分片在 Node 2 和 Node 3 上对应的副本分片提高为主分片, 此时集群的状态将会为 yellow 。 这个提高主分片的过程是瞬间发生的,如同按下一个开关通常。

为何咱们集群状态是 yellow 而不是 green 呢? 虽然咱们拥有全部的三个主分片,可是同时设置了每一个主分片须要对应2份副本分片,而此时只存在一份副本分片。 因此集群不能为 green 的状态,不过咱们没必要过于担忧:若是咱们一样关闭了 Node 2 ,咱们的程序 依然 能够保持在不丢任何数据的状况下运行,由于 Node 3 为每个分片都保留着一份副本。

若是咱们从新启动 Node 1 ,集群能够将缺失的副本分片再次进行分配,那么集群的状态也将如图 5 “将参数 number_of_replicas 调大到 2所示。 若是 Node 1 依然拥有着以前的分片,它将尝试去重用它们,同时仅从主分片复制发生了修改的数据文件。

到目前为止,你应该对分片如何使得 Elasticsearch 进行水平扩容以及数据保障等知识有了必定了解

相关文章
相关标签/搜索