Elasticsearch概述篇

152 阅读15分钟

概述

Elasticsearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java语言开发的,并作为Apache许可条款下的开放源码发布,是一种流行的企业级搜索引擎。Elasticsearch用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。官方客户端在Java、.NET(C#)、PHP、Python、Apache Groovy、Ruby和许多其他语言中都是可用的。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr,也是基于Lucene。

Elasticsearch 逻辑设计

Elasticsearch通过索引、类型、与 ID 唯一确定了某篇文档

image.png

image.png

  • 文档 Elasticsearch 是面向文档的,也就是说索引和搜索数据的最小单位是文档。一篇文档通常是 JSON 表示的数据比如一本书可以这样表示:
{
	"title": "卢浮地宫",
	"writer": "马克-安托万·马修"
}
  • 类型 类型是文档的逻辑容器,类似于数据库表是行记录的容器。因此,如果不同类型的文档,应该放入对应的类型中。例如,图书与读者不同,所以我们可以定义一个图书类型与一个读者类型加以区别。类型中字段的定义称为映射。例如, 图书类型中的 writer 字段可以映射为 string,存储作者信息。

image.png

  • 索引 索引是类型的容器,每个类型包含了一系列的文档集合。索引还存储了一些设置项,比如 refresh_interval,表示新近加入索引的文档对于搜索可见的时间间隔,即刷新频率。默认每秒更新一次,这也被称为准实时。

Elasticsearch 物理设计

理解数据在物理是如何组织的,归根到底是理解elasticsearch 是如何扩展的。

image.png

  • 分片 简单来讲就是咱们在ES中所有数据的文件块。Elasticsearch 所能处理的最小单元就是分片。一个分片实际是 Lucene 的索引,即一份包含倒排索引的文件目录。倒排结构,使得不用扫描所有文档的情况下,就能找到所需要的文档。

一个 Elasticsearch 索引被分为多个分片。因为 Elasticsearch 是使用 Apache Lucene 作为核心的程序库实现数据索引和搜索功能。所以 Elasticsearch 的一个分片就是一个 Lucene 的索引,也就是说ー个Elasticsearch 索引实际是由多个 Lucene 索引组成的。

主分片的数量无法动态的修改。

  • 分片副本 在索引写入时,副本分片做着与主分片相同的工作。新文档首先被索引进主分片然后再同步到其它所有的副本分片。增加副本数并不会增加索引容量。

分片副本可以服务于读请求,如果你的索引也如常见的那样是偏向查询使用的,那你可以通过增加副本的数目来提升查询性能。

分片副本可以容灾,如果没份分片至少有一个副本分片,那么任何一个elasticsearch 都可以宕机,而elaticsearch 依然可以进行服务返回所有的数据。

副本分片可以动态的更新

索引文档

默认情况下,索引某一篇文档,系统会首先根据文档 ID 的散列值选择一个主分片,并将该文档发送到该主分片。有可能主分片在另一个节点,比如下图 中的节点 B 的主分片 1。对应用来说,这一点是透明的。接着,该文档被发送到该主分片的所有副本分片进行索引,比如该文档会从下图 中的节点 B 的主分片 1 发送到节点 A 的副分片 1,实现数据同步。

image.png

搜索索引

当搜索一个索引时, Easticsearch 需要在该索引的完整分片集合中进行查找 ( 即图 中节点 A 的所有主、副分片 ),因为有数据同步机制,所以主分片和副本分片中的文档是相同的。而且 Elasticsearch 会对搜索请求在索引的主、副分片中,进行负载均衡。

image.png

实际情况是,Elasticsearch 使用 round-robin 轮询机制来选择可用的分片 ( 主分片或副本分片 ) ,并将搜索请求转发到相应的分片。

image.png

然后 Elasticsearch 会从这些分片收集结果,接着对这些结果进行聚集,最后将聚集后的结果返回给搜索应用。

image.png

Elasticsearch 配置

  • elasticsearch.yml
  • logging.yml 主要日志:cluster-name.log 慢搜索日志: cluster-name_index_search_slowlog.log 慢索引日志: cluster-name_index_indexing_slowlog.log
  • slasticsearch.in.sh (启动项配置)

elasticsearch 集群

ELasticsearch的集群是由多个节点组成的,通过cluster.name设置集群名称,并且用于区分其它的集群,每个节点通过node.name指定节点的名称。

查看集群状态:/_cluster/health

image.png

image.png

节点角色

Master,集群管理

  • 配置文件中node.master属性为true(默认为true),就有资格被选为master节点。
  • master节点用于控制整个集群的操作。比如创建或删除索引,管理其它非master节点等 Voting,投票选举节点 Data,数据节点
  • 配置文件中node.data属性为true(默认为true),就有资格被设置成data节点。
  • data节点主要用于执行数据相关的操作。比如文档的CRUD。 Ingest,数据编辑节点 Coordinate,协调节点 Machine Learning,集群学习节点

向集群中加入节点

1、修改配置文件集群的名称,后启动实例

2、当另外一个节点加入的时候,ELasticsearch 会自动的将分片在所有的节点上进行均匀分配

image.png

发现其他 ELasticsearch 节点

ELasticsearch 使用二种不同方式发现另外一个节点:广播或者单播。ELasticsearch 可以同时使用二者,不过默认的配置是仅使用广播,因为单播需要已知节点的列表进行连接。

  • 广播 当Elasticsearch启动的时候,它发送了广播(multicast)的ping请求到地址224.2.2.4的端口54238。而其他的Elasticsearch节点使用同样的集群名称,响应了这个请求。注意,如果elasticsearch.yml配置文件中的cluster.name设置了同样的集群名称,那么在同一个局域网下就会有集群节点的加入。 可以进行如下配置:
# 广播地址
discovery.zen.ping.multicast.group=224.2.2.4
# 广播端口
discovery.zen.ping.multicast.port=54238
# 广播消息的TTL。默认是3
discovery.zen.ping.multicast.ttl=3
# 绑定的地址,默认为null,即绑定所有可用的network接口
discovery.zen.ping.multicast.address=null
  • 单播

单播发现(unicast discovery)让Elasticsearch连接一系列的主机,并试图发现更多关于集群的信息。当节点的IP地址不会经常发生变化,或者Elasticsearch的生产系统只连接特定的节点而不是整个网络的时候,单播是很理想的模式

使用单播时,我们告诉Elasticsearch集群中其他节点的IP地址以及端口和端口范围。如下,是单播配置的示例

discovery.zen.ping.unicast.hosts=["10.0.0.3","10.0.4:9300","10.0.0.5[9300-9400]"]

没有必要关闭单播发现。如果只使用了广播发现来查找Elasticsearch节点,在配置文件中将列表保持空白。

选举主节点和识别错误

一旦集群中的节点发现了彼此,它们会协商谁称为主节点。主节点负责管理集群的状态,也就是当前的设置和集群中分片、索引以及节点的状态

在主节点被选举出来后,它会建立内部的ping机制来确保每个节点在集群中保持活跃和健康,这被称为错误识别(fault detection)。

可以通过如下查看集群选举了哪个节点作为主节点:

_cluster/state/master_node,nodes?pretty

删除集群中的节点

删除节点,如下图所示,其中包含了测试的索引5个主分片和每个主分片对应的一个副本分片都分布在这3个节点上。 image.png

如果此时节点1宕机,那么节点1上的3个分片就会丢失,而Elasticsearch会自动将节点2上的test0和test3副本分片转为主分片。由于索引操作会首先更新主分片,所以Elasticsearch要尽力使索引的主分片正常运作。

副本分片转为主分片之后,集群就会变为黄色的状态,意为着某些副本分片尚未分配到某个节点。Elasticsearch下一步需要创建更多的副本分片来保持test索引的高可用性。由于所有的主分片现在都是可用的,节点2上的test0和test3主分片的数据会复制到节点3上作为副本分片,而节点3上test1主分片的数据会复制到节点2

一旦副本分片被重新创建,并用于弥补损失的节点,那么集群将重新回归绿色的状态,全部的主分片及其副本分片都分配到了某个节点。注意,如果失去的节点超过1个,或者某个没有副本分片丢失了,那么集群就会变为红色的状态,就是说某些数据永远地丢失了

就副本分片的数量而言,有1份副本分片意为着集群可以丢失1个节点而不丢失数据。如果有2个副本分片,可以丢失2个节点而不丢失数据,依次类推。

停用节点

当集群进行例行维护的时候,例如需要关闭某个包含数据的节点,而同时不让集群进入黄色的状态。如果直接杀掉Java进程来停止节点,那么Elasticsearch会将数据恢复到其他节点,但是如果你的索引没有副本分片,就会不预先将数据转移的情况下,关闭节点就会丢失数据。

所以这个时候Elasticsearch提供了一种停用节点(decommission)的方式,告诉集群不要再分配任何分片到某个或一组节点上。

假设节点1、节点2和节点3的IP地址分片是:192.168.10.19、192.168.10.20和192.168.10.21。如果你想关闭节点1同时保持集群为绿色状态,可以先停用节点,这个操作会将待停用节点上的所有分片转移到集群中的其他节点

curl -XPUT -H 'Content-Type: application/json' 'http://localhost:9200/_cluster/_settings' -d '{"transient":{"cluster.routing.allocation.exclude._ip":"192.168.10.19"}}'

此时再去关闭192.168.10.19上节点就不会出现黄色或者红色的状态了,因为在执行这个指令的时候,192.168.10.19上的数据都被转移到可用节点上去了。

扩展策略

Elasticsearch的使用方式各有各的不同,所以需要根据如何索引和搜索数据,为集群选择最佳的配置。通常来说,规划生产环境的Elasticsearch集群至少有3件事情需要考虑:过度分片、将数据切分为索引和分片、最大化吞吐量

过度分片

过度分片(over-sharding)是指你有意地为索引创建大量分片,用于未来增加节点的过程。如下图所示:

image.png 在上图中,已经创建了拥有单一分片、无副本分片的boos索引,但是,在增加了另一个节点后,并没有因为增加集群节点所带来的的好处,因为全部的索引和查询负载仍然是由拥有单一分片的节点所处理,所以即使增加了一个节点你也无法进行扩展。

如果现在有一个5个节点、11个主分片的集群,那么当你需要加入更多的节点来处理额外的请求时,就有成长的空间。使用同样的例子,如果你突然需要多于11个节点,就不能在所有的节点中分发主分片,因为节点的数量将会超出分片的数量。

如果你一开始就创建了很多的主分片,由于每个分片都是完整的Lucene索引,所以Elasticsearch需要为索引的每个分段创建一些文件描述,增加相应的内存开销,也就需要更多的硬件来支撑;此外,在压缩数据的时候,需要将数据分为更多不同的内容,造成了硬件资源浪费。

需要注意的是,没有对所有按理适用的完美分片。Elasticsearch选择的默认设置是5个分片,对于普通的用例来说是可以的,但是考虑你的规划在将来是如何增长所建分片的数量,这是一件很重要的事情。一旦索引被创建,其主分片的数量永远不能改变。如果事先没有充分的规划,后期会有大部分的数据不得不重建。

将数据切分为索引和分片

现在还没有办法让我们增加或者减少某个索引中的主分片数量,但是你总可以对数据进行规划,让其横跨多个索引。这是另外一种完全合理的切分数据的方式。 如:日志按照日期切分或者活动按照城市切分

最大化吞吐量

  • 加快索引 加速索引的一个方式是临时地减少集群中副本分片的数量。索引数据的时候,默认情况下,在数据更新到主分片和所有副分片之前,请求是不会完成的。

  • 加快搜索 通过加入更多的副本可以检索的更快。这是因为无论是主分片还是副本都可以用于搜索。如果搜索请求量太大,集群中的节点很难对付,那么考虑加入节点是将这些节点node.data 和node.master 设置为false。这些节点就可以用于处理不断涌入的请求,将请求分发到数据节点,收集返回的结果。

别名

索引别名可以指向一个或多个索引,并且可以在任何需要索引名称的API中使用。 别名为我们提供了极大的灵活性。它们允许我们执行以下操作:

  • 在正在运行的集群上的一个索引和另一个索引之间透明切换;
  • 对多个索引进行分组组合(例如,last_three_months的索引别名:是过去3个月索引logstash_201903, logstash_201904, logstash_201905的组合);
  • 在索引中的文档子集上创建“视图”(结合业务场景,会提升检索效率)。

路由

如何以通过分片形式来定位文档,这个过程被称为路由(routing)文档。

Elasticsearch的路由机制即是通过哈希算法,将具有相同哈希值的文档放置到同一个主分片中。这个和通过哈希算法来进行负载均衡几乎是一样的。

而Elasticsearch有一个默认的路由算法:它会将文档的ID值作为依据将其哈希到相应的主分片上,这种算法基本会保持所有数据在所有分片上的一个平均分布,而不会产生数据热点。

默认情况下Elasticsearch使用文档的ID将文档平均的分布于所有的主分片上,这导致了Elasticsearch不能确定文档的位置,所以它必须将这个请求广播到所有1分片上执行。这同时是也解释了为什么主分片的数量在索引创建的时候就是固定的,不能改变。因为如果分片的数量改变了,所有先前的路由值就会变成非法了,文档相当于丢失了。

而自定义路由模式,可以使我们的查询更具有目的性。这时我们告诉Elasticsearch我们的数据在哪个分片上。

例如,如果查询语句是:请告诉我,USER1的文档数量一共有多少?

使用自定义路由后的查询结果是:它就在第三个分片上,其他的分片就不要去扫描了。

备份

使用无论哪个存储数据的软件,定期备份你的数据都是很重要的。Elasticsearch 副本提供了高可靠性;它们让你可以容忍零星的节点丢失而不会中断服务。

但是,副本并不提供对灾难性故障的保护。对这种情况,你需要的是对集群真正的备份——在某些东西确实出问题的时候有一个完整的拷贝。

要备份你的集群,你可以使用 snapshot API。这个会拿到你集群里当前的状态和数据然后保存到一个共享仓库里。这个备份过程是"智能"的。你的第一个快照会是一个数据的完整拷贝,但是所有后续的快照会保留的是已存快照和新数据之间的差异。随着你不时的对数据进行快照,备份也在增量的添加和删除。这意味着后续备份会相当快速,因为它们只传输很小的数据量。

常用api

参考 blog.shangsw.com/articles/20…