Elasticsearch基础知识介绍
本篇主要介绍elasticsearch的一些基本知识和原理,如es中索引、文档等概念,文档索引的请求过程。
其内容主要来自官方文档:Elasticsearch官方入门文档
1. 基本概念
1.1 集群(Cluster)
多个节点通过配置同一cluster.name名来组成集群;
集群状态:
- 绿色:所有主分片和副本分片都正常运行
- 黄色:所有主分片都正常运行,但不是所有的副本分片都正常运行
- 红色:有主分片没能正常运行
当集群状态未红色时,说明有些节点的数据是不可用的,应尽快修复。
查看集群状态命令:/_cluster/healt
1.2 节点(node)
一个运行的ES实例便是一个节点,用来提供索引和搜索功能。节点在启动时会自动分配一个UUID作为唯一标识,如果要加入集群,只需多个几点设置同样的cluster.name即可。
1.3 索引(index)
索引是某些具有相似文档的集合,可以理解为关系数据库的数据库。
索引名称必须全部小写。
1.4 类型(type)
6.0版本之前,用于在同一索引中区分多个类型的文档,在6.0之后版本已经弃用。限制一个索引只能有一种类型的文档集合。可以理解为关系数据库的表。
1.5 文档(Document)
文档是索引的基本单元,一个索引包含多个文档。文档以json格式表示。可以理解为关系数据库的行。
文档由很多json field构成,field可以理解为关系数据库的列。
ES中文档是不可以被更新,只可以被替换。至于api中的部分更新接口实际上还是通过获取旧的文档,将制定列更新之后进行替换的。
1.6 分片(Shards)
索引可能包含超过单个节点容量的文档,且如果单个几点数据量过大会影响到搜索速度。
因此es通过将索引拆分成多个分片来解决大容量问题,每个分片有以下优点:
* 水平扩展/缩放内容量
* 跨分片(可能跨节点)分布和并行化操作,提高性能/吞吐量
数据的多个分片可能分布在不同的节点中,因此发生故障导致分片数据不可用的概率也上升,为了解决这个问题,es通过使用给分片创建副本的方式来提供可用性。
主分片数目在集群创建时确定,但副本的数目可以动态修改。
1.7 副本(Replica)
副本是对分片的复制,目的是当分片/节点出现故障时,可以从副本读取数据,从而提高吞吐量。
总之,每个索引可以分成N个分片,每个分片也可以复制M份。这个值可以在创建索引时设定也可以在后期动态修改。但是如果索引文档较多,这个操作会很耗时,一般不推荐这种操纵,因此最好的方式就是一开始就计算好分片和副本的数量。
es默认为每个索引提供5个分片和1个副本。但es的主分片和副本不能存在同一个节点上,因为这样对高可用无帮助,因此要提升可用性,必须构建es集群。
2. 集群相关
2.1 索引请求的处理过程
主节点负责管理集群范围内的所有变更,如增加、删除索引,或者增加、删除节点等。但主节点不需要涉及到文档级别的变更和搜索操作,因此即使集群只有一个主节点,也不会成为性能瓶颈。
- 单个文档请求的处理
用户可以将请求发送到集群中的任意节点,每个节点都知道任意文档的位置,并且能够将请求转发到存储文档的节点,然后将文档信息收集后返回给客户端。
- 故障后主节点的选举算法
(待补充)
2.2 ES并发的处理
- ES内部版本号
采用乐观锁控制方式,在获取数据修改之后,带上获取时的version,更新时如果不是当前version,则失败。 实际上这种情况jr好早之前便已使用。
es的更新、删除api都支持version参数,这样能有效的控制并发的问题。
- 外部版本号
有时ES只是作为搜索引擎,而主数据可能存在于外部的关系型数据库中,所有数据的更改通过其他方式同步到es中,当多个进程负责数据同步时,也会产生同时处理一个数据的情况。
此时,es的api方法中的version参数的校验方式便发生了变化,区别与es内部版本后的梳理,我们在api中通过version_type=external的方式来表示这是一个外部版本号,然后es对此的处理方式则是检查数据当前的版本号是否小于制定版本号。
如下面命令在更新时会判断文档的版本是否小于10,若是则操作成功,否则失败。
PUT /website/blog/1?version=10&version_type=external
- ES的批量处理大小
一般来说根据不同的实际情况(硬件性能、文档大小)会有不同的批量适合值。可以通过1000-5000个文档的批次来测试这个最佳性能点,但要注意批量的大小应该控制在5-15M之间。
- 分布式文档存储
- 路由文档
索引一个文档时,文档会被存储到一个主分片上,但是如何确定这个到哪个主分片呢?ES的采用如下路由算法:
shard = hash(routing) % number_of_primary_shards
routing默认是文档的id,也可以设置一个自定义的值。根据公式可以讲文档索引到0到shards-1的主分片中。
这样的路由算法决定了我们无法在索引创建后更改主分片的数量,因为主分片的值一旦改变,原来所有的路由算法就会失效。
所有的文档api都支持routing参数,有时我们可以使用这个参数将确保所有相关文档(如同一用户文档)都存到同一个分片中。