Elasticsearch核心技术与实战-学习笔记
Elasticsearch
-
es 提供了四种级别的倒排索引配置 ,可以控制倒排索引记录的内容,docs 记录docid ,freqs记录doc id 和term frequencies ,positions记录 docid,term frequencies, term positions, offset 记录 dicid,term frequencies, term positions, character offset
-
null_value 实现对 null的搜索
-
多字段特性
-
index template 在索引创建时生效,修改template不会影响已经创建的索引,可以指定多个template,按照指定的order 合并在一起
- 1、应用Elasticsearch默认的mappings和settings
- 2、应用order 比较低的template
- 3、应用order 比较高的template
- 4、应用创建索引时指定的template
-
dynamic Template 是定义在某个具体的索引的Mapping中,template有一个名称,匹配规则是一个数组,为匹配到的字段设置mapping
-
自我测试题
- update 一个doc 需要使用post,而非put ,put 只能index和create,index和create的区别?
- match_phrase的slop是什么意思
- text字段类型设置not index时也不能被搜索到
-
相关度算法
- TF-IDF
- BM25
-
结构化查询 term 是包含而不是一个精确的相等
- query 中boost和boosting查询,query context和filter context
-
分词器
- 哈工大标准
- HanLP
- 查字典
- 北航梁南园教授
- 哈工大-王晓龙,最小词数分词理论
- 基于统计学模型(解决二异性词)清华郭进
- 基于统计的机器学习算法
-
TMDB数据库
-
search template解耦搜索和dsl语言,使开发、搜索、性能工程师各司其职,类似数据库的存储过程的思想
-
7版本以上不用设置min_master_number
-
不设置副本分片会导致不能进行故障转移(提高读能力),主分片过小会导致,数据量增大后,不能水平扩展。主分片过打,导致每个分片数据量小,一个节点上的shard过多,也会影响性能。
-
倒排索引的不可变性,一旦生成不能修改,好处:1、不用并发写,不会产生锁 2、便于加入内存,一旦加入内存,就留在哪里(内存足够大),提高缓存命中率 3、便于维护和压缩 坏处:1、需要重新建立,才能保证被搜索到(?建立segment就行吧)
-
refresh ,把index buffer写入segment(文件系统缓存),默认一秒一次。flush 把内存中的segment写入磁盘(调用fsync),默认30分钟。
-
index buffer默认10% JVM的大小,transaction log 默认大小512M, 满了后会触发对应的refresh和flush操作
-
merage 会自动合并磁盘上的segmen文件(多合并一个,真正的删除)
-
es的搜索分为两个阶段:query then fetch,query阶段各data节点会返回(from+size)doc id 和sort值,到协调节点,协调节点重新排序后,在通过muti-get获取到真正的doc,返回给调用者。
-
排序
- 默认,不能对text,进行排序。对text进行排序需要在mapping中该字段的fielddata设置成ture
- 默认用,_scroe评分排序,用sort排序后, _scroe为null
- 排序是对索引原文进行排序的,所以不能使用倒排索引,要使用正排索引
- doc values 是正排索引,同时是列存数据,用来排序和聚合分析,在index时和倒排索引同时建立,占用磁盘空间,占用index时间,是ES2.x后默认使用的排序方式。不排序不聚合可以关闭掉。
- field data是正排索引,是查询时才建立,不占用磁盘空间和index时间,但是占用java heap,数据量大时会引起OOM,ES 1.X的默认排序实现,现在已经不推荐使用。除非text排序和聚合分析用。
-
分页
- _search?scroll=5m 会建立一个查询时的快照,后插入的文档查询不到,5m应该时快照的存活时间,快照占用磁盘空间么?
-
版本并发控制
- 内部版本控制:if_seq_no+if_primary_term (原来的内部version 已经被废除了?)
- 使用外部版本:version+version_type=external
-
聚合分析
- terms, 需要字段打开field data, keyword默认打开,text字段默认关闭field data ?
- terms 可以通过设置mapping中字段的参数,使字段进行预计算,提高terms桶的性能
- 聚合分析的作用域:query查询出来的结果集合,aggs中的filter,post_filter,global也可以从不同的方面影响聚合的结果集
-
聚合分析的准确性:
- 分布式大数据计算平台:数据量、准确性、实时性(等边三角形的顶点),只能满足两个。大数据量和准确性=hadoop离线计算平台
- ES 计算不准确的原因是协调节点无法看到数据的全貌,解决方法(对terms聚合):
- 数据量不大时,用一个主分片,数据是准确的
- 设置shard_size,每个shard上多获取数据,来提高准确性,默认的shard_size=size*1.5+10
-
Elasticsearch的建模
- 关系型数据库范式化设计的主要目的:减少不必要的更新。完全范式化面临查询缓慢的问题,join增多。
- Elasticsearch主要考虑反范式化设计,嵌套对象和数组兑现的区别。嵌套对象的查询和聚合分析需要指定 nested path, 嵌套对象是存储在两个Lucence中
- ES7中的父文档和子文档也是索引在一个索引中的,存储在一个分片(shard)中。和ES5.x中的type本质上没区别,嵌套对象和父子文档的区别
-
Elasticsearch重建索引
- 场景:mappings 发生改变,settings主分片发生改变,集群内和集群间做迁移
- 方法:
- update by query :现有索引做重建
- reindex:在其他索引上重建
- _source 必须是enable
- 必须先建立dest index的_setting,_mappings等
-
ingest node
- ingest可以对index,_bulk 进入的es的数据进行预处理,想当于logstash的功能,默认每个节点都是ingest角色
-
painless script
- 5.x引入,6.x之后只能用painless
- 扩展了java语法,支持所有的java类型和API,支持动态定义类型
- 用于对文档字段的加工处理
- 更新删除字段,处理聚合,script filed,function score
- ingest pipleline中执行
- reindex,update_by_query中对数据进行处理
- 编译开销想当大,默认缓存100个编译后的脚本,可以调整缓存大小和编译频率,缓存超时等
-
数据建模
-
数据建模的一般过程 概念模型-》逻辑模型-》数据模型(第三范式),考虑功能需求和性能需求
-
字段类型选择-》是否全文检索-》是否聚合排序-》是否额外存储
- _source enable为false结合store为true使用,一般不建议关闭_source,不能reindex和update
- term 查询在query 和 filter 上下文中表现是否一致
-
建模建议
-
文档关系: object=>nested=>父子关系;
- kibana对nested和父子关系支持不好,做数据可视化需要作出取舍
-
一个文档中字段不要过多,mappings保存在cluster state中,字段过多会造成性能问题
- mapping中字段默认不能超过1000,
- 字段过多通常是由于 dynamic mapping 开启造成的,可以使用nested object和key/value的方法解决
-
避免正则查询
- 解决方法:冗余或拆分字段,用空间换时间
-
避免null值导致聚合不准确
-
为mapping加入meta信息进行版本管理(结合git)
-
-
-
第二部分总结
- term 查询和 match查询的区别
- term是精确(不论是text还是keyword)
- match对text是会做分词查询,对keyword会自动转换成term查询
- filter context和query context的区别(不理解)
- filter 避免算分且利用缓存
- bool中filter和must not 都是filter
- term 查询和 match查询的区别
-
集群安全
- server host:0.0.0.0 四个零代表什么?
- 可以通过tls和ca证书来保护9300端口在节点间的信息传输,防止未经认证的节点加入集群和传输泄密
-
集群部署
-
节点角色
-
master eligible node
- 主备节点:管理集群状态,负责index的创建、分片管理、、mapping元数据等
- 机器配置:低cpu\低内存\低磁盘
-
data node
- 负责数据的存储、搜索和聚合计算
- 机器配置:高cpu\高内存\高磁盘
-
ingest node
- 负责数据处理
- 机器配置:高cpu/高内存/低磁盘
-
coordinate node(协调节点)
- 扮演loadbance 角色。降低master和node的负载,负责搜索查询结果的聚合和reduce
- 机器配置:高cpu\高内存\低磁盘
-
marching learning node
-
-
部署方式
- 协调节点:数据节点:master节点
- 读写分离方式 协调节点|ingest节点:数据节点:master节点
- 可以通过设置节点属性来实现hot/warm和不同机架分布
-
环境参数检查
- jvm 参数:
- xms 和 xmx 设置一样,避免resize时造成停顿
- jvm 有swapping 的功能么?
- 集群参数设置的四种范式和优先级
- transient settings
- persistent settings
- command-line settings
- config file settings
- os参数设定的要求
- 不超过 物理内存的50%,不超过32g
- 搜索类内存磁盘比例 1:16,日志类 1:50
- 最好ssd,不需要raid,用机械硬盘要关闭 current merges
- ssd 测试:https://www.elastic.co/blog/is-your-elasticsearch-trimmed
- jvm 参数:
-
集群监控
- 有_cluster|_nodes /stats和index/_stats 三个级别的状态监控
- _tasks和_cluster/_pending_tasks查看任务
- _nodes/thread_pool和_nodes/stats/thread_pool 和 _cat/thread_pool 和_nodes/hot_threads 可以查看集群相关的信息
-
集群健康状态
- 分片健康、索引健康、集群健康,可以通过api查看三个级别的健康状况
- 分片为分配的原因,可以通过_cluster/allocation/explan 查看
- 分片没有分配的其他原因
- 新建索引有短暂的变红
- 集群重启阶段
- index_reopen
- Dangling_index_reimported ,一个节点离开集群期间,有索引被删除,这个节点再回来时会导致dangling问题,再删除一次索引可以解决
-
提高集群的写入
- bluk api/线程数量,查看是否返回429,需要自动重试和调整线程数量
- 使用es自己生成的doc id,用自己的id时,es在index时会先有get操作
- 减少不必要的cpu和存储开销(不必要的分词、doc values,文档字段顺序相同,提高压缩率)
- 最重要的是高质量的数据建模
- 关闭不必要的功能
- 只聚合不搜索:index 设置成false
- 不需要算分 norms设置成false
- 不要对字符串使用默认的dynamic mappings
- index_options 控制倒排索引的内容,可以节约一定量的cpu
- 关闭_source(使用于指标型数据,影响reindex和update)
- 调整写入过程参数
- refresh
- refresh_interval和静态参数indices.memory.index_buffer_size一同调节
- translog
- index.translog.durability,默认request(每次请求落盘),async 实现异步写入
- index.translog.sync_interval设置60s,每分钟写一次
- index.translog.flush_threshod_size:512mb,超过后也会出发flush
- flush
- es自动完成,可调整内容不多
- refresh
-
提高集群的读性能
- 尽可能的反规范化
- nested 会慢几倍
- parent/children 会慢几百倍
- 尽量先计算,避免script
- 尽量使用filter context,利用缓存减少不必要的算分
- 结合profile和explan api 查找原因
- 严禁使用* 开头的通配符查询,严重影响集群性能
- force-merge read-only 索引
- 尽可能的反规范化
-
-
Elasticsearch测试
- ES官方的开源测试工具Elastic Rally
- Elasticsearch 段合并优化
- es 的一个shard = Luence的一个index
- Lucence的一个index 包含多个 segment,segment commits 记录一个index的所有 segment
- 优化方法
- 一、降低segment 产生的数量和频率
- refresh interval和indices.memory.index_buffer_size
- 减少更新
- 二、避免大段参与合并
- 设置segment段的最大大小
- index.merge.policy.max_merged.segment
- index.merge.policy.segments_per_tier 什么含义呢?
- 设置segment段的最大大小
- 一、降低segment 产生的数量和频率
- es 的一个shard = Luence的一个index
- Elasticsearch 缓存
- 分类
- node query cache: 每个节点都有,所有shard共享,缓存 filter context查询,segment合并失效
- shard query cache:shard 所有,缓存agg查询,refresh时失效
- field data cache,缓存text 分词后做聚合查询用,默认无限制,默认不释放,需要设置大小和断路器
- 断路器的分类和设置
- 分类
- 索引管理
- shrink 和 reindex api的区别
- shrink 比 reindex 性能更好,shrink是通过segment硬连接的方式,链接到统一索引,性能比较好
- shrink 限制比较多
- 源shard数据,必须是目标shard数的倍数,如果源是素数,目标必须是1
- 源shard必须在同一个node上
- 分片只读,集群绿色等
- split 和 reindex api的区别
- 性能更好
- 限制更多
- 目标shard数是源shard 数的倍数
- 分片只读
- 不要求分片在同一个node上
- rollover api 可以实现索引的滚动新建立
- 当索引存活超过一定时间、超过设定文档数、超过设定大小会重新建立索引(log4j的appender)
- 但是不会自动触发,需要结合索引管理使用
- shrink 和 reindex api的区别