思维导图
思维导图.png相关开源产品
Kibana
-
Kibana是一个开源的分析与可视化平台,设计出来用于和Elasticsearch一起使用的。你可以用kibana搜索、查看存放在Elasticsearch中的数据。Kibana与Elasticsearch的交互方式是各种不同的图表、表格、地图等,直观的展示数据,从而达到高级的数据分析与可视化的目的
Kibana.png
Cerebro
-
Cerebro是查看分片分配, 部分集群配置最有用的界面之一通过图形界面,可以执行常见的索引操作
Cerebro.png
LogStash
-
logstash就是一根具备实时数据传输能力的管道,负责将数据信息从管道的输入端传输到管道的输出端;与此同时这根管道还可以让你根据自己的需求在中间加上滤网,Logstash提供里很多功能强大的滤网以满足你的各种应用场景
LogStash.png
入门
ES数据建模篇
- es复杂数据结构有: 对象,nested嵌套,父子结构。当然也可以应用层自己关联处理,而不用设置成复杂结构
- 建模准则,字段类型 -> 是否需要搜索和分词 -> 是否需要聚合
对象及nested关系
- 对象结构会被扁平化处理,会丢失对象字段之中的关系。举例
# es插入对象
{
"group" : "fans",
"user" : [
{
"first" : "John",
"last" : "Smith"
},
{
"first" : "Alice",
"last" : "White"
}
]
}
# 扁平化处理,丢失了first,last关系
{
"group" : "fans",
"user.first" : [ "alice", "john" ],
"user.last" : [ "smith", "white" ]
}
- nested嵌套关系,能解决对象扁平化处理问题,在lucene里面会被存储成两个lucene,查询时做关联查询,
# 索引mapping设置成嵌套关系
{
"mappings": {
"properties": {
"user": {
"type": "nested"
}
}
}
}
# es插入对象,此时关联关系会被保存下来
父子关系
- 父子关系实际上两个文档, 举例
# 新建父子文档索引 question(父) -> answer(子)
PUT /my_index?pretty
{
"mappings": {
"properties": {
"my_join_field": {
"type": "join",
"relations": {
"question": "answer"
}
}
}
}
}
# 插入父文档
PUT /my_index/_doc/8?refresh&pretty
{
"text": "This is a question",
"my_join_field": {
"name": "question"
}
}
# 插入子文档
PUT /my_index/_doc/3?routing=8&refresh&pretty //指定 id = 8 的父文档,父子文档要在一个分片
{
"text": "This is an answer",
"my_join_field": {
"name": "answer",
"parent": "8"
}
}
# 通过parent_id查询子文档
GET my_index/_search
{
"query": {
"parent_id": {
"type": "answer",
"id": "8"
}
}
}
# 查询符合要求的父文档
GET my_index/_search
{
"query": {
"has_child" : {
"type" : "answer",
"query" : {
"match_all" : {}
},
"max_children": 10, //可选,符合查询条件的子文档最大返回数
"min_children": 1, //可选,符合查询条件的子文档最小返回数
"score_mode" : "min"
}
}
}
嵌套对象以及父子对象对比
-
父子关系文档更新都是相互对,互不影响的
嵌套对象以及父子对象对比.png
update by query 和 reindex
- update by query api是在现有索引基础上重建,reindex是在其他索引上重建
- 一般在字段类型变更,分词器字典变更,主分片数据变更,数据迁移到新索引
- reindex场景: 修改索引主分片数,修改字段类型(es不允许在原有的字段上更新),跨集群数据迁移
ingest pipeline
- 预处理数据,增强
//创建
PUT _ingest/pipeline/blog_pipeline {
"description":"split tags",
"processors": [
{
"split":{
"field":"tags",
"separator":","
}
}
]
}
// 测试创建的pipeline
POST _ingest/pipeline/blog_pipeline/_simulate
{
"docs":[
{
"index":"index",
"_id":"id",
"_source":{
"tags":"elastic,hadoop,elastic"
}
}
]
}
ES深入篇
聚合
- Bucket聚合: 满足特定条件的文档集合
- Metric聚合:可以对文档字段进行统计分析
- Pipeline聚合:对聚合结果二次聚合
-
Matrix聚合:对多个字段操作弄成矩阵
Bucket和Metric.png
相关性算分
- 一些类似的这种没有啥意义的词,一般不计入算分,可以设置为停用词
- TF-IDF: TF表示检索词在一片文档的频率,IDF就是检索词在所有文档出现频率的log, 评分就是加权
- BM25: 更合理的TF-IDF计算方式,k表示词频对TF score的影响, 避免TF过大造成的影响, k1表示L对TF socore评分的影响,L表示文档长度与平均值, L越小TF score越大,越短的文章,相关性确定的越快
高亮
- 返回的highlight会有em标签,三种高亮介绍
- plain highlight默认
- posting highlight,index_options=offsets
2.1 性能比plain highlight要高,因为不需要重新对高亮文本进行分词
2.2 对磁盘的消耗更少
2.3 将文本切割为句子,并且对句子进行高亮,效果更好 - fast vector highlight对于大于1M的filed,高亮性能更佳
搜索建议
- 两个term的相似性是如何判断的: 将搜索文本分解成token, 然后在索引字典里面找到相似term, 核心思想就是一个词改动多少可以和另一个词一样
- 有四种
- term: 只基于analyze过的单个term去提供建议,并不会考虑多个term之间的关系。missing mode如索引已存在则不提供建议, popular mode推荐出现词频更高的词,always mode无论是否存在都提供建议
- phrase: 在第一种term上加了些逻辑,考量多个term之间关系。max errors最多可拼错多少词,confidence限制返回结果数
- complete: 类似自动补全功能,每发送一个字符就要查询
- context: 第三种的complete拓展,比如输入star, 电影相关的是 star wars,咖啡相关就是starbucks
分片路由
- shard = hash(routing) % number_of_primary_shards
- routing默认是id, number_of_primary_shards主分片数
查询
- multi search批量查询
别名
ES调优篇
写入性能
- 目标: 增大写入的吞吐量
- 客户端可以批量bulk写入,多测测参数调优,bulk写入不要太大,写入轮训到不同节点上
- 服务端: 设置好refresh间隔,使用自动生成的文档id
- 减少不必要的分词,正排索引,负载好些
缓存使用
- Jvm堆内存有Filter,Fielddata,节点查询缓存(比如聚合时用到)
- LRU淘汰缓存
- 除了Text类型,其他都默认Doc Values
- segment合并时,Fielddata会失效
- field data数据过大,segments个数过多时,嵌套查询过多可能造成full gc, 可通过内存api查看占用。各个circuit breaker阈值熔断可以防止full gc
正排索引相关
- 如果不需要排序和聚合enable设置成false,Doc_Values和FieldData设置成false(Doc_Values和FieldData就是用来给文档建立正排索引的。他俩一个很显著的区别是,前者的工作地盘主要在磁盘,而后者的工作地盘在内存)。字段类型为keyword,long,date,那么这些类型修饰的字段一定会有正排索引(Doc values)
- 不需要要检索index设置false
-字段类型不分词则设置字段类型为text - 需要做精确匹配,需要聚合的字段类型可设置成keyword
存储相关
- elasticsearch 会保存一份源文档到 _source ,如果文档的某一字段设置了 store 为 yes (默认为 no),这时候会在 _source 存储之外再为这个字段独立进行存储,这么做的目的主要是针对内容比较多的字段,
放到 _source 返回的话,因为_source 是把所有字段保存为一份文档,命中后读取只需要一次 IO,包含内容特别多的字段会很占带宽影响性能
集群部署相关
线上配置(配置清单 + 集群部署相关)
- 集群节点类型有: master data 协调 ingest
-
有大量复杂查询时可以增加协调节点
增加协调节点.png -
读写分离
读写分离.png - 冷热节点
-
Rack Awareness可以尽量避免主副分片在同一个机架上
image.png - 分片数设计:分片过多会导致聚合查询等额外性能开销,即从不同机器上读取数据。分片过少数据负载不合理。副本过多也不合理毕竟占用资源。搜索类单个分片不要超过20G,索引类不要超过50G
- shrink/split index, 扩大缩小主分片数
- 根据源索引的配置创建一个目标索引,目标索引的主分片数量是index.number_of_routing_shards的因子。这个因子需要大于源索引主分片数
- 然后它将源索引中的segments硬链接到目标索引中。 (如果文件系统不支持硬链接,那么所有segments都被复制到新索引中,这是一个更耗时的过程。硬链接与普通文件没什么不同,inode 都指向同一个文件在硬盘中的区块)
- rollup index,适用于每天新建索引
量级比较高的
- 四台 物理机一台master(应该是有三个备选master节点),qps 500, 内存124g, 87tb
- 每台每秒200,800k/s这样
量级比较一般的
- 三台master候选节点(2C 2G)不负责数据节点,八台数据节点(12C 24G, jvm给了10G),qps 200每台
内存设定,根据需要存储数据估算
- 搜索类: 1:16, 日志类 1:48-1:96
- 假如总数据量1T副本也1T,总共2T数据。
- 搜索类每个节点31(尽量不要超过32G)*16= 496G,去除预留空间所以每个节点最多400G。至少需要5个节点
- 日志类每个节点31*50 = 1550G,2个数据节点就好
- 磁盘容量:影响ES集群磁盘空间的有以下几点,综合考虑,留源数据的3.4倍就好
- 副本数量
- 索引开销
- 操作系统预留
- ES内部开销,比如段合并
- 安全预留
建议
- jvm堆内存不要超过物理内存的百分50
- 可以使用协调节点进行负载
- 关闭动态索引
- 使用x-pack安全
诊断
- 查看索引级别,找到红色索引/_cluster/health?level=indices
- explain变红原因, /_cluster/allocation/explain
- 红表示至少有一个主分片没被分配,黄表示至少有一个副本没被分配,绿是正常。集群不健康原因可能是有集群暂离了,重启之类的
ES实践篇
商城场景
- es与mysql一致性处理:
- Canal监听数据库变更,将数据整合到ES(更新商城这种有公示期非实时,创建内容需要实时搜索到的)
- 同步变更到ES,相对性能不好
网友评论