ElasticSearch从入门到精通–第四话(核心概念篇)
ElasticSearch从入门到精通–第一话(入门篇)
ElasticSearch从入门到精通–第二话(原生API调用–纯代码篇)
ElasticSearch从入门到精通–第三话(集群环境搭建篇)
ElasticSearch从入门到精通–第四话(核心概念篇)
ElasticSearch从入门到精通–第五话(整合SpringBoot高效开发、分页高亮等、Kibana使用篇)
核心概念
索引(Index)
一个索引就是一个用于几分相似特征的文档集合,可以理解为mysql中的一个数据库。
ES中索引的精髓:一切设计都是为了提高搜索的性能
。
类型(Type)
在一个索引中,可以定义一种或多种的类型,可理解为mysql中的表。一个类型就是索引一个逻辑上的分类,语义我们可以自定义。在不同版本,类型的概念逐渐被淡化了。
版本 | Type |
---|---|
5.x | 支持多种Type |
6.x | 支持一种Type |
7.x | 不再支持自定义的Type,有个默认Type名为_doc |
文档(Document)
一个文档就是一个可被索引的基础信息单元,也就是一条数据,理解为mysql中的一行数据。
字段(Field)
相当于是数据表的字段,对文档数据进行不同属性分类的标识,都是以json方式存储的。
映射(Mapping)
Mapping是处理数据格式的方式和规则做一些限制,如:某个字段的数据类型、默认值、分析器、是否要被索引等等。都是可以在映射里面设置的,通常情况下我们可以按照业务场景,建立不同的映射,达到性能最高化。
分片(Shards)
这个可以理解为mysql中数据分表操作,一个索引可以存储的最大数据量中,单个节点处理搜索请求响应太慢。为了解决这个问题,ES提出将索引划分为多份,每一份就是一个分片
。创建索引时我们可以指定分片的数量,每个分片本身也是一个功能完善并且独立的索引
,这个索引
可以被放置到集群中的任何节点上。
分片重要性:
- 允许水平分割、扩展内容容量
- 允许在分片之上进行分布式、并行操作,提高性能和吞吐量。
副本(Replicas)
为了提交服务的高可用性,ES允许创建分片时创建一份或多份拷贝,这些就是复制分片(副本)。
- 副本在分片/节点失败情况下,提供了高可用性,且副本是不与master节点数据在同一个节点的(有点类似kafka集群的分区副本)
- 扩展搜索量,搜索可以在所有的副本上并行运行
ES集群
在完整性较高的ES集群中,首先是多个ES服务器节点,有个master主节点进行管理集群,然后在多个ES节点上存放着索引的多个分区和其他分区的副本(高可用性角度考虑)
分布式集群(演变)
创建索引(多分片)
在一个单节点的ES节点上,创建一个索引,并且分配三个主分片和一个副本(每个主分片都有一个副本分片)
PUT
请求,请求体中,设置
{
"settings":{
"number_of_shards":3,
"number_of_replicas": 1
}
}
然后GET
请求下
分片数量是3,然后副本数量是1
可视化工具
那么集群有没有可视化的一些工具呢,当然有,像kibana、ES Head(谷歌插件)都可以使用。
我这边使用的谷歌的浏览器插件,有兴趣的可以看看教程
进去插件后,连接到这个es服务器
上图中,有一个node-1001的es节点,然后还有上面为灰色的0、1、2(光看users索引的,先别看shopping索引)
灰色的指的是副本
未分配,其实原因呢就是副本数据是不能和主分片数据放在一起的(假如主分片的节点宕机,那么副本同样是用不了的,没有必要去分配副本)。然后它的集群健康值就是呈yellow黄色,指的就是当前集群的全部主分片都正常运行,但是副本没有处在正常状态中
故障转移(最少两台es节点)
说白了,就是启动集群,提高服务高可用性,就算某一个es节点宕机,那么其他的es节点仍可提供服务(因为其他es节点中保存着宕机节点的副本数据)
在上面的基础上,增加es节点,就可达到故障转移的作用。es节点加入集群后,副本数据会进行重分配。
尝试再启动一个es节点后,再去可视化界面看看,集群状态
集群状态变成了green绿色,且副本被分配到了node-1002的节点上面。
代表着每个分片(包括主分片和副本分片)都能对外提供服务,提高系统服务的高可用性。
水平扩容(2台以上es节点)
那么如何为我们正在增长的应用程序按需扩容呢,当启动了第三个es节点时,我们的集群会拥有3个es节点:会为了分散负载而对分片进行重新分配,提高系统吞吐量。
像上面两台es节点时,它的主分片和副本没有均匀放置在整个的集群中,那么就需要进行再扩展节点,达到均匀放置所有分片。
再启动一个es节点,看可视化界面
会发现,所有分片被分配到这三个节点中
再次理解,水平扩容:就是增加es节点,然后分片分配给这个新的es节点上面,达到水平扩展
扩展多台es
当要扩展的数量相对主分片数量较多时,因为刚开始创建索引时主分片数量被确定了,那就是定义了这个索引能够存储的最大数据量。但是读操作、搜索和返回数据是可以同时被主分片或副本分片处理
,所有我们可以去扩展副本分片的数量,达到高吞吐的目的。
将副本的数量,设置为2
{
"number_of_replicas": 2
}
设置每个主分片可以有2个副本,(1+2)*3=9
个分片
应对故障
假如某一台es节点宕机了,master宕机,那么集群会选取一个slave节点成为master节点
可以看到,node-1001节点已经没了,然后选举node-1003为新的master节点
当宕机的节点重新进入集群后,node-1001是作为slave节点存活的。
node-1001的yml配置中,记得配置
discovery.seed_hosts: ["localhost:9303", "localhost:9302"]
主节点仍然是node-1003节点
路由计算
首先要明了,数据要放入某个分片时,一定先放入到主分片中的,因为副本分片只是一个备份,要记得。那么多主分片时,它是如何知道要放入到哪个主分片呢?就涉及到了路由计算
.
(路由计算
)数据存入时的算法:hash(routing)%主分片的数量
每个数据都有一个routing的参数,默认情况下就是文档的_id值即可,将id计算出hash值,然后对主分片的数量进行取余,取余的值就是具体的分区。那么主分片的数量一旦定义好,就不能轻易去更改了,一旦更改,那么之前计算好的所有路由值都会失效,文档就无法被索引了
。
数据写流程
数据传送过来后经过路由计算出要将数据存入到哪个es节点的分片上,那么再把数据发送给相应的es节点上的分片中存入数据,然后将数据发送给副本分片,副本进行同步数据。
- 客户端请求集群节点(任意)-协调节点
- 协调节点将请求转换到指定的节点
- 主分片需要将数据保存
- 主分片把数据发送给副本
- 副本保存数据,进行反馈
- 主分片进行反馈
- 客户端收到反馈
集群中,有一些可选的参数
-
consistency:即一致性。默认设置下,主分片执行写操作时,规定必须要有一定数量的副本处于存活状态才能执行。(为了避免网络分区故障导致的数据不一致),副本存活数量是
(primary+number_of_replicas)/2+1
- 取值
one
:表示主分片状态ok就允许执行写操作 - 取值
all
:表示主分片和副本全部存活状态才允许执行写操作 - 取值
quorum
:部分数量副本存活允许写操作(默认值)
- 取值
数据读流程
- 客户端发送查询请求到协调节点中
- 协调节点计算数据(
hash(routing)%主分片数量
)所在的分片及副本的全部位置 - 轮询方式查询节点
- 将请求转发给某个es节点
- es节点返回结果,返回给客户端
倒排索引
ES使用的一种倒排索引
的结构,适用于快速的全文索引。
原理:通过分词器将数据进行拆解,然后拆解后的词汇分别与文档ID做绑定,达到倒排的目的。当然,不同的分词器有不同的分词策略,根据不同的算法进行拆解。
- 词条:索引中最小存储和查询单元
- 词典:字典,词条的集合,B+,Hash算法
- 倒排表:拆解后的词汇分别与ID做绑定的集合表。
近实时搜索
-
在 Elasticsearch 中,写入和打开一个新段的轻量的过程叫做 refresh 。 默认情况下每个分片会每秒自动刷新一次。这就是为什么我们说 Elasticsearch 是 近 实时搜索: 文档的变化并不是立即对搜索可见,但会在一秒之内变为可见。
-
这些行为可能会对新用户造成困惑: 他们索引了一个文档然后尝试搜索它,但却没有搜到。这个问题的解决办法是用 refresh API 执行一次手动刷新: /users/_refresh
-
并不是所有的情况都需要每秒刷新。可能你正在使用 Elasticsearch 索引大量的日志文件,你可能想优化索引速度而不是近实时搜索, 可以通过设置 refresh_interval , 降低每个索引的刷新频率
{ "settings": { "refresh_interval": "30s" } }
-
refresh_interval 可以在既存索引上进行动态更新。 在生产环境中,当你正在建立一个大的新索引时,可以先关闭自动刷新,待开始使用该索引时,再把它们调回来
# 关闭自动刷新 PUT /users/_settings { "refresh_interval": -1 } # 每一秒刷新 PUT /users/_settings { "refresh_interval": "1s" }