ElasticSearch入门学习

一、elasticsearch简介

​ ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。

1、elasticSearch的使用场景

1、 为用户提供按关键字查询的全文搜索功能。

2、 实现企业海量数据的处理分析的解决方案。大数据领域的重要一份子,如著名的ELK框架(ElasticSearch,Logstash,Kibana)。

2、与其他数据存储进行比较

redis mysql elasticsearch hbase hadoop/hive
容量/容量扩展 较大 海量 海量
查询时效性 极高 中等 较高 中等
查询灵活性 较差 k-v模式 非常好,支持sql 较好,关联查询较弱,但是可以全文检索,DSL语言可以处理过滤、匹配、排序、聚合等各种操作 较差,主要靠rowkey, scan的话性能不行,或者建立二级索引 非常好,支持sql
写入速度 极快 中等 较快 较快
一致性、事务

3、elasticsearch的特点

3.1天然分片,天然集群

es 把数据分成多个shard,多个shard可以组成一份完整的数据,这些shard可以分布在集群中的各个机器节点中。随着数据的不断增加,集群可以增加多个分片,把多个分片放到多个机子上,已达到负载均衡,横向扩展。

ElasticSearch入门学习

在实际运算过程中,每个查询任务提交到某一个节点,该节点必须负责将数据进行整理汇聚,再返回给客户端,也就是一个简单的节点上进行Map计算,在一个固定的节点上进行Reduces得到最终结果向客户端返回。

这种集群分片的机制造就了elasticsearch强大的数据容量及运算扩展性。

3.2天然索引

ES 所有数据都是默认进行索引的,这点和mysql正好相反,mysql是默认不加索引,要加索引必须特别说明,ES只有不加索引才需要说明。

而ES使用的是倒排索引和Mysql的B+Tree索引不同。

全文搜索引擎目前主流的索引技术就是倒排索引的方式。

传统的保存数据的方式都是

​ 记录→单词

而倒排索引的保存数据的方式是

​ 单词→记录

基于分词技术构建倒排索引:

首先每个记录保存数据时,都不会直接存入数据库。系统先会对数据进行分词,然后以倒排索引结构保存。

lucene 倒排索引结构

ElasticSearch入门学习

可以看到 lucene 为倒排索引(Term Dictionary)部分又增加一层Term Index结构,用于快速定位,而这Term Index是缓存在内存中的,但mysql的B+tree不在内存中,所以整体来看ES速度更快,但同时也更消耗资源(内存、磁盘)。

二、elasticsearch的基本概念

1、对象名词解释

cluster 整个elasticsearch 默认就是集群状态,整个集群是一份完整、互备的数据。
node 集群中的一个节点,一般只一个进程就是一个node
shard 分片,即使是一个节点中的数据也会通过hash算法,分成多个片存放,默认是5片。(7.0默认改为1片)
index index相当于table
type 对表的数据再进行划分,比如“区”的概念。但是实际上对数据查询优化的作用有限,比较鸡肋的设计。(6.x只允许建一个,7.0之后被废弃)
document 类似于rdbms的 row、面向对象里的object
field 相当于字段、属性

2、服务状态查询

  • GET /_cat/indices?v 查询各个索引状态

表头的含义

※ health 索引的健康状态

※ index 索引名

※ pri 索引主分片数量

※ rep 索引复制分片 数

※ store.size 索引主分片 复制分片 总占用存储空间

※ pri.store.size 索引总占用空间, 不计算复制分片 占用空间

  • GET /_cat/health?v 服务整体状态查询

※ cluster 集群名称

※ status 集群状态 green代表健康(所有主分片都正常而且每个主分片都至少有一个副本,集群状态);yellow代表分配了所有主分片,但至少缺少一个副本,此时集群数据仍旧完整,主片副本都在单点;red代表部分主分片不可用,可能已经丢失数据。

※ node.total 代表在线的节点总数量

※ node.data 代表在线的数据节点的数量

※ shards active_shards 存活的分片数量

※ pri active_primary_shards 存活的主分片数量 正常情况下 shards的数量是pri的两倍。

※ relo relocating_shards 迁移中的分片数量,正常情况为 0

※ init initializing_shards 初始化中的分片数量 正常情况为 0

※ unassign unassigned_shards 未分配的分片 正常情况为 0

※ pending_tasks 准备中的任务,任务指迁移分片等 正常情况为 0

※ max_task_wait_time 任务最长等待时间

※ active_shards_percent 正常分片百分比 正常情况为 100%

  • GET /_cat/nodes?v 查询各个节点状态

※ heap.percent 堆内存占用百分比

※ ram.percent 内存占用百分比

※ cpu CPU占用百分比

※ master *表示节点是集群中的主节点

※ name 节点名

  • GET /_cat/shards/xxxx 查询某个索引的分片情况

※ index 索引名称

※ shard 分片序号

※ pri rep p表示该分片是主分片, r 表示该分片是复制分片

※ store 该分片占用存储空间

※ node 所属节点节点名

※ docs 分片存放的文档数

三、DSL语法

https://blog.****.net/qq_43297252/article/details/106884010

四、关于shard的划分注意点

由于索引是以天为单位进行建立,如果业务线很多,每个索引又不注意控制分片,日积月累下来一个集群几万到几十万个分片也是不难见到的。

1 shard太多带来的危害

每个分片都有Lucene索引,这些索引都会消耗cpu和内存。

shard的目的是为了负载均衡让每个节点的硬件充分发挥,但是如果分片多,在单个节点上的多个shard同时接受请求,并对本节点的资源形成了竞争,实际上反而造成了内耗。

2 如何规划shard数量

1) 根据每日数据量规划shard数量

以按天划分索引情况为例,单日数据评估低于10G的情况可以只使用一个分片,高于10G的情况, 单一分片也不能太大不能超过30G。所以一个200G的单日索引大致划分7-10个分片。

2) 根据堆内存规划shard数量

另外从堆内存角度,一个Elasticsearch服务官方推荐的最大堆内存是32G。一个10G分片,大致会占用30-80M堆内存,那么对于这个32G堆内存的节点,最好不要超过1000个分片。

3) 及时归档冷数据。

4) 降低单个分片占用的资源消耗,具体方法就是:合并分片中多个segment

3 对Segment(段)的优化

由于es的异步写入机制,后台每一次把写入到内存的数据refresh(默认每秒)到磁盘,都会在对应的shard上产生一个segment。

segment太多的危害:

这个segment上的数据有着独立的Lucene索引。日积月累,如果一个shard是由成千上万的segment组成,那么性能一定非常不好,而且消耗内存也大。

官方优化:

如果尽可能的把小的segment合并成为大segment,这样既节省内存又提高查询性能。于是Es 后台实际上会周期性的执行合并segment的任务。

问题:

但是由于ES担心这种合并操作会占用资源,影响搜索性能(事实上也确实很有影响尤其是在有写操作的时候)。所以有很多内置的限制和门槛设置的非常保守,导致很久不会触发合并,或者合并效果不理想。

手动优化:

可如果是以天为单位切割索引的话,我们其实是可以明确的知道只要某个索引只要过了当天,就几乎不会再有什么写操作了,这个时候其实是一个主动进行合并的好时机。

可以利用如下语句主动触发合并操作:

POST movie_index0213/_forcemerge?max_num_segments=1

验证查询语句:

GET _cat/indices/?s=segmentsCount:desc&v&h=index,segmentsCount,segmentsMemory,memoryTotal,storeSize,p,r

操作:

POST movie_index0213/_forcemerge?max_num_segments=1

验证查询语句:

GET _cat/indices/?s=segmentsCount:desc&v&h=index,segmentsCount,segmentsMemory,memoryTotal,storeSize,p,r