ES相关资料参考:https://blog.csdn.net/laoyang360/article/details/52244917
ES中文社区(下载):https://elasticsearch.cn/
安装配置:https://how2j.cn/k/search-engine/search-engine-start/1691.html
——基本概念
- 面向文档型数据库,
- 索引 index(数据库)一切设计都是为了提高搜索的性能
类型 types(表) 一个index下只能包含一个type,在7.X版本中,Type的概念已经被删除
文档 documents(行)
字段 fields(列)
映射mapping(数据类型) - 一个集群至少有一个节点
一个节点就是一个ES进程
节点可以有多个索引
一个索引有一个主分片,创建索引库的分片数默认1片,在7.0.0之前的版本,默认5片
一个主分片有一个副本(复制分片),考虑到高可用性,副本从不与主分片在同一节点上
一个分片是一个Lucene索引,所以一个ES索引是有多个Lucene索引组成
分片会消耗一定文件句柄、内存以及CPU运转 - 当有节点加入集群中或者从集群中移除节点时,集群将会重新平均分布所有的数据
- 主节点负责管理集群范围内的所有变更(增删索引、节点),不涉及文档变更和搜索,所以流量增加它也不会成为瓶颈
- 创建索引的时候就要确定好主分片的数量,并且不改变这个数量,因为文档路由算法与主分片数量有关,修改数量后,文档就再也找不到了
2. 技术架构
3. 分片和副本机制
- index包含多个shard
- 每个shard都是一个最小工作单元,承载部分数据;每个shard都是一个lucene实例,有完整的建立索引和处理请求的能力
- 增减节点时,shard会自动在nodes中负载均衡
- primary shard和replica shard,每个document肯定只存在于某一个primary shard以及其对应的replica shard中,不可能存在于多个primary shard
- replica shard是primary shard的副本,负责容错,以及承担读请求负载
- primary shard的数量在创建索引的时候就固定了,replica shard的数量可以随时修改
- primary shard的默认数量是5,replica默认是1,默认有10个shard,5个primary shard,5个replica shard
- primary shard不能和自己的replica shard放在同一个节点上(否则节点宕机,primary shard和副本都丢失,起不到容错的作用),但是可以和其他primary shard的replica shard放在同一个节点上
4. 容错机制
如果master node 宕机,此时不是所有的primary shard都是Active status,所以此时的集群状态是red
容错处理
- 选举一台服务器作为master
- 新选举出的master会把挂掉的primary shard的某个replica shard 提升为primary shard,此时集群的状态为yellow,因为少了一个replica shard,并不是所有的replica shard都是active status
- 重启故障机,新master会把所有的副本都复制一份到该节点上,(同步一下宕机后发生的修改),此时集群的状态为green,因为所有的primary shard和replica shard都是Active status
健康状态
- 绿色——最健康的状态,代表所有的主分片和副本分片都可用;
- 黄色——所有的主分片可用,但是部分副本分片不可用;
- 红色——部分主分片不可用。
5. 文档数据路由解析
- 文档路由到分片上
一个索引由多个分片构成,当添加(删除,修改)一个文档时,es就需要决定这个文档存储在哪个分片上,这个过程就称为数据路由(routing) - 路由算法
shard=hash(routing) % number_of_pirmary_shards
示例:一个索引,3个primary shard- 每次增删改查时,都有一个routing值,默认是文档的_id的值
- 对这个routing值使用哈希函数进行计算
- 计算出的值再和主分片个数取余数
- primary shard个数一旦确定就不能修改了
倒排索引:根据value查找key
6. 版本控制
ElasticSearch采用了乐观锁来保证数据的一致性,也就是说,当用户对document进行操作时,并不需要对该document作加锁和解锁的操作,只需要指定要操作的版本即可。当版本号一致时,ElasticSearch会允许该操作顺利执行,而当版本号存在冲突时,ElasticSearch会提示冲突并抛出异常(VersionConflictEngineException异常)
7. 数据类型
- 核心数据类型:
字符型:String包括text和keyword
数字型:long、integer、short、byte、double、float
日期型:date
布尔型:boolean
二进制型:binary - 复杂数据类型:
数组类型、对象类型、地理位置类型
——分片策略
索引的分片完成分配后由于索引的路由机制,是不能重新修改分片数的
- 控制每个分片占用的硬盘容量一般不超过ES的最大JVM的堆空间设置(一般不超过32G)
- 设置分片数一般不超过节点数的3倍
- 节点数 <= 主分片数 * (副本数+1)
- 对于节点瞬时中断的问题,集群默认会等待 1min 来查看节点是否会重新加入,如果在此期间重新加入,则不会触发重新分配。这样可以减少ES在自动再平衡可用分片时所带来的极大开销
写入速度优化
- 加大Translog Flush,目的是降低Iops、Writeblock
- 增加Index Refresh 间隔,目的是减少 Segment Merge 的次数
- 调整Bulk 线程池和队列
- 优化节点间的任务分布
- 优化Lucene层的索引建立,目的是降低CPU和IO
ES堆内存的分配
- 不要超过物理内存的50%
- 堆内存的大小最好不要超过32GB
——基本操作命令
- 查看所有索引:localhost:9200/_cat/indices?v
- _cat 表示查看,indices 表示索引
- 创建索引:(PUT)localhost:9200/product
- product 为索引名
- 创建文档:(POST)localhost:9200/product/_doc
- 创建 / 查看 / 修改 / 删除 指定型唯一标识:(PUT / GET / POST / DELETE)localhost:9200/product/_doc/1
- 删除一个文档不会立即从磁盘上删除,它只是被标记成已删除(逻辑删除)
- 修改一条数据的某个字段:(POST)/product/_update/1
- 内容(Json格式):{“doc”:{“price”:3000}}
- 根据条件删除:(POST)/product/_delete_by_query
- 内容:{“query”:{“match”:{“price”:4000}}}
- 创建 / 查看映射(表结构):(PUT / GET)/student/_mapping
- 内容:{“properties”:{“name”:{“type”:“text”,“index”:true},“sex”:{“type”:“text”,“index”:false},“age”:{“type”:“long”,“index”:false}}}
- index:是否索引,默认true,false则该字段不能用来搜索
——常用查询命令
DSL:domain specialed language (特殊领域语言)
关键字段 | 说明 | 请求接口 | Body:raw | 备注 |
---|---|---|---|---|
match all | 查询所有文档 | localhost:9200/student/_search | {“query”:{“match all”:{}}} | query 代表一个查询对象,里面可以有不同的查询属性; match_all 是查询所有,属于查询类型,match、term、range等 |
match | 匹配查询 | localhost:9200/student/_search | {“query”:{“match”:{“name”:“zhangsan”}}} | |
multi_match | 多个字段匹配查询 | localhost:9200/student/_search | {“query”:{“multi_match”:{“query”:“zhangsan”,“fields”:[“name”,“nickname”]}}} | |
term | 关键字精确查询 | localhost:9200/student/_search | {“query”:{“term”:{“name”:{“value”:“zhangsan”}}}} | |
terms | 多关键字精确查询 | localhost:9200/student/_search | {“query”:{“terms”:{“name”:[“zhangsan”,“lisi”]}}} | |
source | 指定查询字段 | localhost:9200/student/_search | {“source”:[“name”,“nickname”],“query”:{“terms”:{“nickname”:[“zhangsan”]}}} | |
includes 、excludes | 指定 想/不想 显示的字段 | localhost:9200/student/_search | {"_source":{“includes”/“excludes”:[“name”,“nickname”]},“query”:{“terms”:{“nickname”:[“zhangsan”]}}} | |
bool | 组合查询 | localhost:9200/student/_search | {“query”:{“bool”:{“must”:[{“match”:{“name”:"zhangsan:}}],“must_not”:[{“match”:{“age”:“40”}]}}} | must(必须),must_not(必须不)、should(应该) |
range | 范围查询 | localhost:9200/student/_search | {“query”:{“range”:{“age”:{“gte”:30,“lte”:35}}}} | gt 大于,gte大于等于,lt小于,lte小于等于 |
sort | 字段排序 | localhost:9200/student/_search | {“query”:{“match all”:{“name”:“zhangsan”}},“sort”:[{“age”:{“order”:“desc”}},{"_score":{“order”:“desc”}}]} | |
highlight | 高亮显示 | localhost:9200/student/_search | {“query”:{“match”:{“name”:“zhangsan”}},“highlight”:{“pre_tags”:"< font color =‘red’>",“post_tags”: “</ font>”,“fields”:{“name”:{}}}} | |
from size | 分页查询 | localhost:9200/student/_search | {“query”:{“match all”:{}},“sort”:[{“age”:{“order”:“desc”}}],“from”:0,“size”:2} | 默认从0开始 |
aggs | 聚合查询 | localhost:9200/student/_search | {“aggs”:{“max_age”/“min_age”:{“max”/“min”:{“field”:“age”}}},“size”:0} | min最小值,max最大值,avg平均值, |
stats | 聚合 | localhost:9200/student/_search | {“aggs”:{“stats_age”:{“stats”:{“field”:“age”}}},“size”:0} | 一次性返回 count max min avg 和 sum 五个指标 |
aggs+terms | 桶聚合查询 | localhost:9200/student/_search | {“aggs”:{“age_groupby”:{“terms”:{“field”:“age”}}},“size”:0} | 类似于sql中的group by |