ElasticSearch版本:6.5.0(点击跳转官方文档)
Elasticsearch 是一个近实时分布式全文搜索引擎,它基于 Apache Lucene。
1. 近实时
实时的应用程序在严格的时间限制下运行。
也就是说,它们可以在固定的时间内执行操作,时间的限制通常以微秒、毫秒为单位。
elasticsearch提供 接近实时的搜索,新增到 elasticsearch 中的文档在’定期时间’后就可以被检索到。
这个’定期时间’默认是每秒一个状态,但这并不意味着可以保证新文档在一秒就到达索引。
这种 新增数据对搜索的可见行称为"准实时搜索"
2. 分布式
分布式意味着可以动态调整集群规模,弹性扩容,而且操作起来非常简便。
3. 全文
对全部的文本内容进行分析,建立索引,使之可以被搜索,因此称为全文。
4. 集群
一个集群(cluster)由一个或多个拥有相同cluster.name配置的节点组成。
它们共同承担数据和负载的压力;
当有节点加入集群或从集群中移除节点时,集群将会重新平均分布所有的数据。
当新加入节点或删除节点,集群会感知并平衡数据。
集群中的任何节点 通过选举 都有可能成为主节点/Master,当然需要通过配置来获得资格
5. 节点
节点是一个服务器,它是集群的一部分,存储数据,并参与集群的索引和搜索功能
节点有一个名称标识,该名称在缺省情况下是在启动时分配给节点的随机全局惟一标识符(UUID)
6. 节点角色
集群节点角色有:
主节点(master node),数据节点(data node),预处理节点(ingest node),协调节点(coordinating node),部落节点(tribe node)
6.1. 主节点 master node
当一个节点被选举成主节点时,它将负责管理集群范围内节点/索引层面的所有变更。
在 elasticsearch.yml 配置文件中,通过配置 node.master: true 使节点具有被选举为master的资格。
主节点是全局唯一的,从有资格成为master的节点中进行选举。
注意:主节点也可以作为数据节点,但应该尽可能减少其工作;生产环境尽量分离 主节点 和 数据节点
主节点不需要涉及文档级别的变更和搜索等操作;所以当集群只拥有一个主节点的情况下,即使流量的增加它也不会成为瓶颈;
创建独立主节点配置:
1 | node.master: true |
6.2. 数据节点 data node
数据节点 负责保存数据,执行数据的相关操作,例如:CRUD/搜索/聚合等。
数据节点对 CPU 和 IO要求较高
一般情况下,数据的读写流程只和数据节点打交道,除非是异常情况,才会和主节点交互。
创建独立数据节点配置:
1 | node.master: false |
6.3. 预处理节点 ingest node
预处理节点是 5.0版本开始引入的
它允许在写入数据之前,通过事先定义好的processes(处理器)或pipeline(管道),对数据进行某种转换/富化
processes 和 pipeline 会拦截 bulk 和 index请求,在处理后,将文档回传给 index 或 bulk api。
默认情况下,是启用ingest的,
创建一个仅用于预处理的节点:
1 | node.master: false |
6.4. 协调节点 coordinating node
协调节点负责查询时的数据收集、合并以及聚合等操作。
默认的,ElasticSearch集群中所有的节点都是协调节点。
创建一个仅用于协调的节点:
1 | node.master: false |
6.5. 部落节点 tribe node
暂不关注
7. 集群健康
集群健康有三种状态:green、yellow、red。
- green 所有主要分片和复制分片都可用
- yellow 所有主要分片可用,但不是所有复制分片都可用
- red 有主要分片不可用
查看集群健康 curl命令:
1 | curl -XGET 'localhost:9200/_cat/health?v&pretty' |
获取集群机器列表 curl命令:
1 | curl -XGET 'localhost:9200/_cat/nodes?v&pretty' |
8. 分片(主分片、副本分片)
8.1. 分片
索引可能存储大量数据,这些数据可能超过单个节点的硬件限制。
为了解决这个问题,Elasticsearch提供了将索引细分为多个碎片(分片)的功能,每个碎片(分片)称之为shard;
索引数据被分配到各个分片上(相当于一桶水用了N个杯子装)。
分片有助于横向扩展
分片:是底层的基础读写/工作单元,它仅保存全部数据中的一部分
分片的目的是分割索引,让读写可以并行操作,由多台机器共同完成。
一个分片就是一个Lucene实例,它本身就是一个完整的搜索引擎。
我们的文档被存储到分片内,应用程序直接与索引交互而不是分片。
分片是数据的容器,文档保存在分片内,分片又被分配到集群中的各个节点中。
elasticsearch 将分片区分成两部分,即 主分片 和 副本分片。
索引内任意一个文档都归属于一个主分片,所以 主分片的数量决定了索引能够保存的最大数据量。
一个副本分片只是一个主分片的拷贝。副本分片作为故障时保护数据不丢失的冗余备份,并且为搜索/读操作提供服务。
注意:索引建立的时候就已经确定主分片数量,索引建立后不可更改,但副本分片数量可以随时更改。
8.2. 主分片
主分片:作为权威数据,写过程中 先写主分片,成功后再写副本分片;恢复阶段以主分片为准。
8.3. 副本分片
副本分片指的是主分片的副本,是shard的复制(分片的冗余备份,防止某个分片挂了,数据丢失)
副本之所以重要,主要有两个原因:
在shard/node失败的时候,它提供高可用性。正因为如此,复制的shard(简称shard的副本)绝不会跟原始shard在同一个节点上
它允许扩展搜索量/吞吐量,因为搜索可以并行地在所有副本上执行
在不同场景下,副本分片有不同的作用
故障
如果集群中,持有主分片的节点故障了,一个副本分片就会晋升为主分片。
写数据
新文档首先被索引(存储)到主分片中,然后再同步到其他所有的副本分片中。
增加副本分片数量,并不会增加索引容量。
读数据
副本分片不论何时,都可以提供 读/搜索 功能。
如果索引偏向查询使用,可以通过增加副本分片数量,提高查询性能;(硬件资源也要增加)
图例:
8.4. 注意
主分片数量是在创建索引时就确定的,索引创建完成后不可更改,主分片数量决定了这个索引能 存储/写入 多少数据量。
但是,搜索/读取 操作,可以同时被 主分片和副本分片处理,所以,拥有越多的副本分片,也将拥有越高的数据吞吐量。
9. 索引
索引(index)这个词在elasticsearch中有不同的含义,有必要区分一下:
索引(名词):这个索引,就像是传统关系型数据库中的数据库,在Elasticsearch中它是相关文档存储的地方,索引实际上是指向一个或多个物理分片的逻辑命名空间。
索引(动词):“索引一份文档”,表示把一个文档存储到索引(名词)里,以便它可以被检索或查询。这很像SQL中的insert关键字,差别是,如果文档已经存在,新的文档回覆盖旧的文档。
反向索引(或传统数据库其他类型的索引):数据结构;传统数据库为特定列增加一个索引,例如B-Tree索引来加速检索。elasticsearch、Lucene使用一种叫做倒排索引的数据结构来达到相同的目的。
10. 映射类型
在elasticsearch 6.0.0 版本之前,一个索引可以包含多个映射类型
Indices created in Elasticsearch 6.0.0 or later may only contain a single mapping type.
Indices created in 5.x with multiple mapping types will continue to function as before in Elasticsearch 6.x.
Types will be deprecated in APIs in Elasticsearch 7.0.0, and completely removed in 8.0.0.
– Removal of mapping types
在elasticsearch 6.0.0 版本之后,索引只能包含一个映射类型。
映射类型是索引中逻辑的种类/分区,它的语义完全取决于自己。
一般情况下,一个映射类型被定义成一组常见字段的文档。
如果把索引看做数据库、类型看做表、映射就是表结构。请注意,仅为了加速理解。这种对比并不好,数据库表可以创建多个,但Elasticsearch6.x版本后,一个index只支持一个type
elasticsearch对于映射类型处理有两种方式:动态映射、静态映射
详细见:ElasticSearch-基础-05-Mapping_数据类型
11. 文档
document(文档)是索引信息的基本单位。
例如,您有一存储 customer(客户)数据的文档,另一个是存储 product(产品)数据的文档,还有一个是存储 order(订单)数据的文档。
该文档可以使用 JSON 来表示,它是一种无处不在的互联网数据交换格式。
在索引/类型中,您可以存储许多文档。注意,尽管一个文档物理的存在于索引中,实际上一个文档必须被 索引/分配 给索引内的类型。
12. 路由
当索引(动词/存储)一个文档时,它被存储在某个主分片中。
Elasticsearch 是如何划分的?怎么决定A文档写到shard-A分片中,而不是shard-B分片中去呢?
Elasticsearch中有一个算法:将数据均匀的分配到各个分片的算法。
1 | shard = hash(routing) % number_of_primary_shard |
上面表达式中的routing是一个变量,如果不设置,默认是文档id,也可以是自定义的值。
routing值hash后,除以主分片数量,得到一个余数(这个余数值范围永远是 0 ~ number_of_primary_shard-1)。
最后得到的值,即是 文档所在的分片。
这里也解释了 为什么主分片数量在创建索引后就不允许修改了。
如果主分片数量修改了,那之前的路由值也就失效了,文档再也检索不到了。
所有文档API(get、index、delete、bulk、mget)都接收一个routing参数,它用来自定义文档到分片的映射。
自定义路由值可以确保所有相关文档,例如属于同一人的文档,都保存在同一分片上。
13. 加深理解
将elasticsearch和传统数据库进行比较,以此来理解elasticSearch中的概念:
DB | ElasticSearch |
---|---|
DataBases(数据库) | Index/Indices(索引) |
Tables(表) | Types(映射类型) |
Rows(行) | Documents(文档) |
Columns(列) | Fields(字段) |
(仅是为了加速理解,不能真的以此进行横向比较,在Elasticsearch6.0.0或更高版本中创建的索引可能只包含单个映射类型)
14. Reference
在ElasticSearch中,集群(Cluster),节点(Node),分片(Shard),Indices(索引),replicas(备份)之间是什么关系?
《Elasticsearch in Action》
《Elasticsearch源码解析与优化实战》
《Elasticsearch 权威指南》