ES集群架构
- Mannager只负责分配,不负责路由:使用raft协议选举mannager,然后将分配信息同步给所有节点,类似kafka
- 节点分片互为主备:每个节点存储一部分主分片,一部分副本分片。分片是目录索引维度的,混杂
- client负载均衡请求任意存储节点,此节点整合信息
重要概念
- ES主要用来搜索分析全文检索模糊匹配等,Mongo主要用来存储
- 分片:分片是目录索引维度的。默认使用文档id分片,主分片个数不能修改,副本个数可以修改
- 不支持修改:底层是Lucene,只能先删除再新增。所以不适合高频修改的场景
- 主从分片复制:同步异步半同步
- 主从一起查询:可以指定查询主分片/副本分片。默认一起负载均衡,都有可能
- 没有库表概念:只有索引 创建索引(类似创建数据库)PUT /users,类似于创建一个目录。每个目录索引有自己的分片。不同索引的分片混杂在节点
- 落盘时机:ES操作有缓存,删除也是标记为待删除,新增文档在缓存生成一个段,段写满或者刷新时间到 refresh_interval控制,每次操作会先写入缓冲区(无法查询到),每一秒或者缓冲区满Refresh操作 生成一个新的段,写入文件系统缓存,可以被查询搜索到。每30分钟强制flush一次文件系统强制落盘,删除Translog,生成新的日志文件
- 安全与崩溃恢复:每次操作会写日志Translog,每个写请求都会触发一次日志fsync强制落盘
- 段合并:大量标记为待删除的垃圾数据,以及大量小段数据,需要段合并合并为大段(Segment),同时清理掉垃圾数据,每一个段都是一个倒排索引
- 倒排索引:是按照字典序排序的。所以无法支持范围查询。更适合等值查询。
- 列存DocVlues:倒排索引不能范围查询,每个分片有自己的DocValues,可以快速在自己的分片范围查询
- 深分页:每个分片重新查询算分数,排序。使用search_after,每个分片节点直接根据上一次的lastValues截断,只返回size文档数给协调者节点,协调者再归并排序,截取size数量。如果不使用search_after 使用from+size,每个分片就需要把全量数据排序后 把前面的数据全部返回,没办法截断的,局部排序没办法决定位置,协调者需要归并排序再截断。主要是每个分片返回的文档的数量太多
数据类型与倒排索引:
- 每个字段都可以生成自己的倒排索引
- text类型:默认加索引,会自动进行分词后,生成倒排索引
- keyword类型:默认加索引,不分词
- 数值类型
- GEO类型
- 嵌套类型:如果直接存储一个对象数组,ES会将其扁平化,所以需要声明type为nested
分析器
包括字符过滤器(Character filters)、分词器(Tokenizer)、词元过滤器(Token filters)
- 字符过滤器:分词之前的预处理,例如删除html标签,字符替换等
- 分词器:ik_smart分词器、ik_max_word分词器对中文分词友好
- 词元过滤器:将分词后的词元,进行大小写转换,过滤长度过小的词元 等等
- 默认分析器Standerd:例如text字段,如果不指定,就会使用默认分析器
- 自定义分析器:type: customer 指明这是一个自定义分析器
- 查询使用的分析器:使用search_analyzer指定
- 插入使用的分析器:使用analyzer指定
创建索引
创建映射,默认所有字段都会加索引。也可以显示设置index:true/false
文档支持动态扩展字段,即使映射没有声明,也可以动态添加字段
创建mappings有一个字段dynamic:true/false/strict
- dynamic:true动态添加字段也都会加索引,有映射爆炸的风险。有可能创建大量索引出来
- dynamic:false动态添加的字段 不加索引,不能作为查询条件。但是会存储
- dynamic:strict不允许动态添加字段,否则报错
PUT/test_index_false{"mappings":{"dynamic":false"properties":{"title":{"type":"text","index":true// 明确可搜索},"description":{"type":"text","index":false// ❗关键:有映射但不建索引},"user_id":{"type":"keyword","index":false// 不建索引}}}}