ES 总结

简介

es的数据结构和传统数据库的数据结构

es的文档型数据结构(json) 能够直观的 表达 基于面向对象的 数据(多层嵌套的数据关系)

传统数据库 只能分表分对象,查询时 需要关联。

es 分布式,高可用,大数据量,少更新,近实时的查询,聚合,分析的文档数据 存储系统

分布式:集群部署,数据分散存储,提高查询性能和存储能力

高可用:数据存储在不同node和不同shard中保证数据安全部丢失,并且primary shard会有对应的 replica,保证查询数据完整不缺失,replica 也支持查询提高了服务的性能和并发能力。

大数据量:可分布式支持了它可以垂直扩容和横向扩容,大大提高了数据的存储能力。

少更新:因为所有的更新操作不管是es 提供 的put 或者 partial update api 都是需要先查询后再删除元数据,在新增新数据。而不是直接更新,效率是比较低的。

近实时

1.一个是查询数据近实时,因为保存的数据时间大概需要1秒,所以能查询的到数据是1秒之后。

2.查询数据的速度是秒级别

文档数据:document 数据的基础单位,格式就是json,多关系数据嵌套。

存储系统:如何数据存储,primary shard必须要有replica的并且自动负载均衡(shard会 自动 均匀分布在node上,每当有新的node加入,shard会重新分布)

作用:

查询,全文检索,短语检索,排序,过滤,高亮:match all 查询所有,match 包含,multi match 多字段,range query,term query 精确查询(查询词语 不分词),terms query 指定多个搜索条件

(1)对商品信息进行CRUD(增删改查)操作

(2)执行简单的结构化查询

(3)可以执行简单的全文检索(分词后检索),以及复杂的phrase(短语)检索(就是不分词,进行检索)

(4)对于全文检索的结果,可以进行高亮显示

(5)对数据进行简单的聚合分析

 

基础概念

0.近实时 :1.保存数据后一秒才能查询 2.查询数据速度快秒级别

1.node 节点

2.cluster集群(node是集群中的一个单元)

3.index 索引 (建议同类型同业务放同一个index,不同业务数据查询不会互相影响,适合放document中filed大部分相同的)索引名称必须是小写的,不能用下划线开头,不能包含逗号

4.type 类型   代表document属于index中的哪个类别(type),一个索引通常会划分为多个type,逻辑上对index中有些许不同的几类数据进行分类,就比如说,商品,可能划分为电子商品,生鲜商品,日化商品,type名称可以是大写或者小写,但是同时不能用下划线开头,不能包含逗号,lucene是没有type的概念的,在document中,实际上将type作为一个document的field来存储,所以一个index下的多个type的数据结构 field 是合并在一起的,如果没有数据就是“”,所以filed相差太多的document放在同个index下性能是很差的

5.document 文档

6.field 字段

7.shard 分片 每个shard都是一个lucene实例,每个node都是一个es实例,primary shard不可新增,replica 数量可以修改(数据index 会被保存在不同的shard上) 默认一个shard要对应一个副本并且他们不在同一个节点。所以高可用的es需要部署两台机器,primary shard(建立索引时一次设置,不能修改,默认5个),replica shard(随时修改数量,默认1个),默认每个索引10个shard,5个primary shard,5个replica shard,最小的高可用配置,是2台服务器。

8.replica 副本 (shard的数据会被复制到replica上,replica 也是shard)replica可以在shard故障时提供备用服务,保证数据不丢失,多个replica还可以提升搜索操作的吞吐量和性能。

elasticsearch核心概念 vs. 数据库核心概念

Elasticsearch			数据库

-----------------------------------------

Document			行
Type				表
Index				库

     9._id元数据  代表document的唯一标识,与index和type一起,可以唯一标识和定位一个document

    10._source元数据 整个文档数据的一个字段,如果某个字段内容非常多,业务只需要能对该字段进行搜索,最后返回文档id,查看文档内容会再次到HBase中取数据,把大字段的内容存在Elasticsearch中只会增大索引,这一点文档数量越大结果越明显,如果一条文档节省几KB,放大到亿万级的量结果也是非常可观的

    11._version  乐观锁并发策略

es自己的 版本控制:每次对document的更新都会对这个_version版本号自动加1;哪怕是删除(不是立即物理删除掉的),也会对这条数据的版本号加1

基于自己version实现并发控制:

version_type=external,唯一的区别在于,_version,只有当你提供的version与es中的_version一模一样的时候,才可以进行修改,只要不一样,就报错;当version_type=external的时候,只有当你提供的version比es中的_version大的时候,才能完成修改

    12.took:整个搜索请求花费了多少毫秒

    13.hits.total:本次搜索,返回了几条结果

    14.hits.max_score:本次搜索的所有结果中,最大的相关度分数是多少,每一条document对于search的相关度,越相关,_score分数越大,排位越靠前

    15.hits.hits:默认查询前10条数据,完整数据,_score降序排序

    16.mapping  自动或手动为index中的type建立的一种数据结构和相关配置  ,dynamic mapping,自动为我们建立index,创建type,以及type对应的mapping,mapping中包含了每个field对应的数据类型,以及如何分词等设置

    注意:搜索结果为什么不一致,因为es自动建立mapping的时候,设置了不同的field不同的data type。不同的data type的分词、搜索等行为是不一样的。所以出现了_all field和post_date field的搜索表现完全不一样。

不同的数据类型(比如说text和date),可能有的是exact value(不分词),有的是full text(分词后建立倒排索引),比如说exact value搜索的时候,就是直接按照整个值进行匹配,full text query string,也会进行分词和normalization再去倒排索引中去搜索

mapping,就是index的type的元数据,每个type都有一个自己的mapping,决定了数据类型,建立倒排索引的行为,还有进行搜索的行为

    17. store 默认关闭,将字段存储在磁盘,查询时优先从store获取,文档很长,检索所有文档或者存储所有文档、获取所有field的代价比较大,此时可以使用

    18._all 全文检索(不指定具体字段)

ES 特点 和 架构

1.分布式的透明隐藏性:

1.0集群的发现机制,新的node会自动被集群发现

1.1不用关注document保存在 哪个分片 shard

1.2不用关注分片的负载均衡(1.会均匀把分片分布到node上 2.es 会自动将负载比较重的node中把分片迁移到新加入的节点)

1.3不用关注replica分布,es会自动创建

1.4shard副本,请求路由,集群扩容,shard重分配

2、Elasticsearch的垂直扩容与水平扩容

垂直扩容看成本 和 单机的处理能力

水平扩容看成本 和 并发能力

3、增减或减少节点时的数据rebalance

不用关注分片的负载均衡(1.会均匀把分片分布到node上 2.es 会自动将负载比较重的node中把分片迁移到新加入的节点)

4.master节点 的作用

节点 索引的创建 和删除

5、节点平等的分布式架构

每个节点功能都是一样 可以处理请求,路由请求,收集数据,响应结果。

shard&replica机制

(1)index包含多个shard

(2)每个shard都是一个最小工作单元,承载部分数据,lucene实例,完整的建立索引和处理请求的能力

(3)增减节点时,shard会自动在nodes中负载均衡

(4)primary shard和replica shard,每个document肯定只存在于某一个primary shard以及其对应的replica shard中,不可能存在于多个primary shard

(5)replica shard是primary shard的副本,负责容错,以及承担读请求负载

(6)primary shard的数量在创建索引的时候就固定了,replica shard的数量可以随时修改

(7)primary shard的默认数量是5,replica默认是1,默认有10个shard,5个primary shard,5个replica shard

(8)primary shard不能和自己的replica shard放在同一个节点上(否则节点宕机,primary shard和副本都丢失,起不到容错的作用),但是可以和其他primary shard的replica shard放在同一个节点上

Elasticsearch容错机制:master选举,replica容错,数据恢复

1.一个node挂掉,如果是master 会 重新选举 (cluster status :red)

2.把挂掉node中的primary shard的replica 变成 primary(cluster status : yellow)

3.重启挂掉的node,并且把原来的 primary shard变成 replica,从新的primary shard的同步过来(cluster status:green)

router 数据路由 和 请求路由

1.每个document 都要通过路由算法得出最终要保存在哪个shard上。路由算法:shard = hash(routing) % number_of_primary_shards  

默认的routing就是document id,也可以在发送请求的时候,手动指定一个routing value

手动指定routing value是很有用的,可以保证说,某一类document一定被路由到一个shard上去,那么在后续进行应用级别的负载均衡,以及提升批量读取的性能的时候,是很有帮助的

2.primary shard数量不可变的谜底

因为新增的primary shard后,路由算法中有用到 primary shard 的总数 发生改变,路由到的shard 会是错的。

document 查询原理

1、客户端发送请求到任意一个node,成为coordinate node

2、coordinate node对document进行路由,将请求转发到对应的node,此时会使用round-robin随机轮询算法,在primary shard以及其所有replica中随机选择一个,让读请求负载均衡

3、接收请求的node返回document给coordinate node

4、coordinate node返回document给客户端

5、特殊情况:document如果还在建立索引过程中,可能只有primary shard有,任何一个replica shard都没有,此时可能会导致无法读取到document,但是document完成索引建立之后,primary shard和replica shard就都有了

 

倒排索引 和 搜索词语 (分词 和 转换 normalization)  延展到 正排索引

建立单词和文档id的索引,建议例子说明

doc1 : I like you
doc2 : I love you

分词后初步的倒排索引的建立

word  doc
I      doc1,doc2
like   doc1
love   doc2
you    doc1,doc2 

但是liked 其实 和 like 意思差不多 但是查不到

normalization 建立倒排索引的时候,会执行一个操作,也就是说对拆分出的各个单词进行相应的处理,以提升后面搜索的时候能够搜索到相关联的文档的概率

时态的转换,单复数的转换,同义词的转换,大小写的转换

这样同义词也就可以查询到 提高 搜索命中率

缺点:倒排索引不可变的坏处:每次都要重新构建整个索引

 

doc value之正排索引

在建立索引的时候,一方面会建立倒排索引,以供搜索用;一方面会建立正排索引,也就是doc values,以供排序,聚合,过滤等操作使用

doc values是被保存在磁盘上的,此时如果内存足够,os会自动将其缓存在内存中,性能还是会很高;如果内存不足够,os会将其写入磁盘上排序的时候,需要依靠正排索引

doc1: { "name": "jack", "age": 27 }
doc2: { "name": "tom", "age": 30 }

document	name		age

doc1		jack		27
doc2		tom		    30	

 

写一致性原理consistency以及quorum机制深入剖析

默认是同步复制,当number_of_replicas>1时并且满足consistency  索引才会成功,写失败 有可能是 写一致性原理导致

设置一致性consistency  put /index/type/id?consistency=quorum

one:要求我们这个写操作,只要有一个primary shard是active活跃可用的,就可以执行

all:要求我们这个写操作,必须所有的primary shard和replica shard都是活跃的,才可以执行这个写操作

quorum:默认的值,要求所有的shard中,必须是大部分的shard都是活跃的,可用的,才可以执行这个写操作

quorum机制,写之前必须确保大多数shard都可用

quorum不齐全时,wait,默认1分钟,timeout,100,30s

我们其实可以在写操作的时候,加一个timeout参数,比如说put /index/type/id?timeout=30,这个就是说自己去设定quorum不齐全的时候,es的timeout时长,可以缩短,也可以增长

_source的作用

(1)查询的时候,直接可以拿到完整的document,不需要先拿document id,再发送一次请求拿document

(2)partial update基于_source实现

(3)reindex时,直接基于_source实现,不需要从数据库(或者其他外部存储)查询数据再修改

(4)可以基于_source定制返回field

(5)debug query更容易,因为可以直接看到_source

 

ES的基础操作

es document id 的指定

 手动指定document id  根据根据业务系统的primary key 指定

 也可以es自动生成document id

mget批量查询

可以说mget是很重要的,一般来说,在进行查询的时候,如果一次性要查询多条数据的话,那么一定要用batch批量操作的api,尽可能减少网络开销次数,可能可以将性能提升数倍,甚至数十倍,非常非常之重要

就是一条一条的查询,比如说要查询100条数据,那么就要发送100次网络请求,这个开销还是很大的,如果进行批量查询的话,查询100条数据,就只要发送1次网络请求,网络请求的性能开销缩减100倍

更新文档 partial update 比put性能更好

       PUT 流程是先get获取到所有信息在修改数据写入es(put请求其实es将老的document标记为deleted,然后重新创建一个新的document),partial update是查询,修改和写回操作均发生在同一个shard内,并且内置乐观锁并发控制

注意: 用put更新,需要传全部字段,所以要先get,而partial update 只有传需要更新的字段并且更新中es的查询,修改都是在shard内部完成,时间间隔短,减少了并发更新的几率。

分页 以及 deap paging 性能

deep paging 底层原理就是 他会把请求发送到所有分片数据 并且 都要返回要查询的数据的总行数之前的数据(比如我要查1000页,那就是10000条到10010条,各个分片就要返回10010的数据给协调节点)返回给coordinate node,协调节点 在进行排序,返回目标行数。产生的问题:性能比较差,shard 返回的数据比较多,要尽量减少deap paging

bulk 允许一次多个操作 批量增删改

bulk操作中,任意一个操作失败,是不会影响其他的操作的,但是在返回结果里,会告诉你异常日志,bulk request会加载到内存里,如果太大的话,性能反而会下降,因此需要反复尝试一个最佳的bulk size。一般从1000~5000条数据开始,尝试逐渐增加。另外,如果看大小的话,最好是在5~15MB之间。

filter 和 query 的深度对比

差别

filter,仅仅只是按照搜索条件过滤出需要的数据而已,不计算任何相关度分数,对相关度没有任何影响

query,会去计算每个document相对于搜索条件的相关度,并按照相关度进行排序

性能:

filter,不需要计算相关度分数,不需要按照相关度分数进行排序,同时还有内置的自动cache最常使用filter的数据

query,相反,要计算相关度分数,按照分数进行排序,而且无法cache结果

搜索大量数据 scoll 数据滚动

使用scoll滚动搜索,可以先搜索一批数据,然后下次再搜索一批数据,以此类推,直到搜索出全部的数据来

游标查询会取某个时间点的快照数据。 查询初始化之后索引上的任何变化会被它忽略。 它通过保存旧的数据文件来实现这个特性,结果就像保留初始化时的索引 视图 一样。

每次查询如果返回scoll id那可以根据这个id继续查询数据

修改分词器以及定制自己的分词器

默认的分词器  standard,也可以自定义分词器

standard tokenizer:以单词边界进行切分

standard token filter:什么都不做

lowercase token filter:将所有字母转换为小写

stop token filer(默认被禁用):移除停用词,比如a the it等等

基于scoll+bulk+索引别名实现零停机重建索引

一个field的设置是不能被修改的,如果要修改一个Field,那么应该重新按照新的mapping,建立一个index,然后将数据批量查询出来,重新用bulk api写入index中

批量查询的时候,建议采用scroll api,并且采用多线程并发的方式来reindex数据,每次scoll就查询指定日期的一段数据,交给一个线程即可

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值