Elasticsearch集群
分布式集群
Elasticsearch可以在分布式环境中运行,你可以随时根据你的需求扩展Elasticsearch,你可以购买配置更好的主机或者购买更多地主机来达到扩展的目的。
硬件越强大,Elasticsearch运行的也就越快,但是垂直扩展方式也有它的局限性。真正的扩展来自于横向扩展方式,在集群中添加更多的节点,这样能在节点之间分配负载。
对于大多数的数据库来说,横向扩展意味着你的程序往往需要大改,以充分使用这些新添加的设备。相比而言,Elasticsearch自带分布式功能:他知道如何管理多个节点并提供高可用性。这也就意味着你的程序根本不需要为扩展做任何事情。
空集群
如果我们启用一个既没有数据,也没有索引的单一节点,那我们的集群看起来就像是这样
节点是Elasticsearch运行中的实例,而集群则包含一个或多个具有相同cluster.name的节点,它们协同工作,共享数据,并共同分担工作负荷。由于节点是从属集群的,集群会自我重组来均匀地分发数据。
集群中的一个节点会被选为master节点,它将负责管理集群范畴的变更,例如创建或删除索引,添加节点到集群或从集群删除节点。master节点无需参与文档层面的变更和搜索,这意味着仅有一个master节点并不会因流量增长而成为瓶颈。任意一个节点都可以成为master节点。我们例举的集群只有一个节点,因此它会扮演master节点的角色。
作为用户,我们可以访问包括master节点在内的集群中的任一节点。每个节点都知道各个文档的位置,并能够将我们的请求直接转发到拥有我们想要的数据的节点。无论我们访问的是哪个节点,它都会控制从拥有数据的节点收集响应的过程,并返回给客户端最终的结果。这一切都是由Elasticsearch 透明管理的。
集群健康
在 Elasticsearch集群中可以监控统计很多信息,其中最重要的就是:集群健康(cluster health)。它的 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 是我们最应该关注的字段。 status可以告诉我们当前集群是否处于一个可用的状态。三种颜色分别代表:
状态 | 意义 |
---|---|
green | 所有主分片和从分片都可用 |
yellow | 所有主分片可用,但存在不可用的从分片 |
red | 存在不可用的主要分片 |
添加索引
为了将数据添加到Elasticsearch,我们需要索引(index) ——存储关联数据的地方。实际上,索引只是一个逻辑命名空间(logical namespace),它指向一个或多个分片(shards)。
分片(shard)是工作单元(worker unit)底层的一员,它只负责保存索引中所有数据的一小片。分片是一个独立的Lucene实例既可,并且它自身也是一个完整的搜索引擎。我们的文档存储并且被索引在分片中,但是我们的程序并不会直接与它们通信。取而代之,它们直接与索引进行通信的。
在 elasticsearch中,分片用来分配集群中的数据。把分片想象成一个数据的容器。数据被存储在分片中,然后分片又被分配在集群的节点上。当你的集群扩展或者缩小时,elasticsearch会自动的在节点之间迁移分配分片,以便集群保持均衡。
分片分为主分片(primary shard) 以及从分片(replica shard)两种。在你的索引中,每一个文档都属于一个主分片,所以具体有多少主分片取决于你的索引能存储多少数据。
虽然理论上主分片对存储多少数据是没有限制的。分片的最大数量完全取决于你的实际状况:硬件的配置、文档的大小和复杂度、如何索引和查询你的文档,以及你期望的响应时间。
从分片只是主分片的一个副本,它用于提供数据的冗余副本,在硬件故障时提供数据保护,同时服务于搜索和检索这种只读请求。
索引中的主分片的数量在索引创建后就固定下来了,但是从分片的数量可以随时改变。
接下来,我们在空的单节点集群中上创建一个叫做 blogs的索引。一个索引默认设置了5个主分片,但是为了演示,我们这里只设置3个主分片和一组从分片(每个主分片有一个从分片对应):
PUT /blogs
{
"settings" : {
"number_of_shards" : 3,
"number_of_replicas" : 1
}
}
现在,我们的集群看起来就像下图所示了有索引的单节点集群,这三个主分片都被分配在 Node 1。
如果我们现在查看 集群健康(cluster-health) ,我们将得到如下信息:
{
"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 <2>
}
集群的 status 为 yellow.我们的三个从分片还没有被分配到节点上。集群的健康状况yellow意味着所有的主分片(primary shards)启动并且运行了,这时集群已经可以成功的处理任意请求,但是从分片(replica shards)没有完全被激活。事实上,当前这三个从分片都处于unassigned(未分配)的状态,它们还未被分配到节点上。在同一个节点上保存相同的数据副本是没有必要的,如果这个节点故障了,就等同于所有的数据副本也丢失了。现在我们的集群已经可用了,但是依旧存在因硬件故障而导致数据丢失的风险。
增加故障转移
在单一节点上运行意味着有单点故障的风险,没有数据冗余备份。幸运的是,我们可以启用另一个节点来保护我们的数据。
只要第二个节点与第一个节点的cluster.name相同(参见./config/elasticsearch.yml文件中的配置),它就能自动发现并加入到第一个节点的集群中。如果没有,请结合日志找出问题所在。这可能是多播(multicast)被禁用,或者防火墙阻止了节点间的通信。
如果我们启动了第二个节点,这个集群应该叫做双节点集群(cluster-two-nodes),双节点集群——所有的主分片和从分片都被分配:
当第二个节点加入后,就产生了三个从分片(replica shards) ,它们分别于三个主分片一一对应。也就意味着即使有一个节点发生了损坏,我们可以保证数据的完整性。
所有被索引的新文档都会先被存储在主分片中,之后才会被平行复制到关联的从分片上。这样可以确保我们的文档在主节点和从节点上都能被检索。
当前,cluster-health 的状态为green,这意味着所有的6个分片(三个主分片和三个从分片)都已激活:
{
"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
}
集群的 status 是 green. 我们的集群不仅功能齐全的,并且具有高可用性。
横向扩展
随着应用需求的增长,我们该如何扩展?如果我们启动第三个节点,集群内会自动重组,这时便成为了三节点集群(cluster-three-nodes)。 分片已经被重新分配以平衡负载:
在Node 1和Node 2中分别会有一个分片被移动到Node 3上,这样一来,每个节点上就都只有两个分片了。这意味着每个节点的硬件资源(CPU、RAM、I/O)被更少的分片共享,所以每个分片就会有更好的性能表现。
分片本身就是一个非常成熟的搜索引擎,它可以使用单个节点的所有资源。我们一共有6个分片(3个主分片和3个从分片),因此最多可以扩展到6个节点,每个节点上有一个分片,这样每个分片都可以使用到所在节点100%的资源了。
扩展更多
但是如果我们想要扩展到六个节点以上应该怎么办?
主分片的数量在索引创建的时候就已经指定了,实际上,这个数字定义了能存储到索引中的数据最大量(具体的数量取决于你的数据,硬件的使用情况)。例如,读请求——搜索或者文档恢复就可以由主分片或者从分片来执行,所以当你拥有更多份数据的时候,你就拥有了更大的吞吐量。
从分片的数量可以在运行的集群中动态的调整,这样我们就可以根据实际需求扩展或者缩小规模。接下来,我们来增加一下从分片组的数量:
PUT /blogs/_settings
{
"number_of_replicas" : 2
}
增加number_of_replicas到2: 从图中可以看出,现在 blogs 的索引总共有9个分片:3个主分片和6个从分片。也就是说,现在我们就可以将总节点数扩展到9个,就又会变成一个节点一个分片的状态了。最终我们得到了三倍搜索性能的三节点集群。
故障恢复
前文我们已经提到过Elasticsearch可以应对节点故障。让我们来尝试一下。如果我们把第一个节点杀掉,我们的集群就会如下图所示:
被杀掉的节点是主节点。而为了集群的正常工作必须需要一个主节点,所以首先进行的进程就是从各节点中选择了一个新的主节点:Node 2。
主分片1和2 在我们杀掉Node 1后就丢失了,我们的索引在丢失主节点的时候是不能正常工作的。如果我们在这个时候检查集群健康状态,将会显示 red:存在不可用的主节点!
幸运的是,丢失的两个主分片的完整拷贝在存在于其他的节点上,所以新的主节点所完成的第一件事情就是将这些在 Node 2 和 Node 3 上的从分片提升为主分片,然后集群的健康状态就变回至 yellow。这个提升的进程是瞬间完成了,就好像按了一下开关。
那么为什么集群健康状态依然是是 yellow而不是green 呢?是因为现在我们有3个主分片,但是我们之前设定了1个主分片有2个从分片,但是现在却只有1份从分片,所以状态无法变为green,不过我们可以不用太担心这里:当我们再次杀掉 Node 2的时候,我们的程序依旧可以在没有丢失任何数据的情况下运行,因为 Node 3中依旧拥有每个分片的备份。
如果我们重启Node 1,集群就能够重新分配丢失的从分片,这样结果就会与三节点两从集群一致。如果 Node 1依旧还有旧节点的内容,系统会尝试重新利用他们,并只会复制在故障期间的变更数据。