美文网首页
ElasticSearch原理与实战

ElasticSearch原理与实战

作者: 后来丶_a24d | 来源:发表于2022-02-19 19:17 被阅读0次

    思维导图

    思维导图.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深入篇

    聚合

    1. Bucket聚合: 满足特定条件的文档集合
    2. Metric聚合:可以对文档字段进行统计分析
    3. Pipeline聚合:对聚合结果二次聚合
    4. Matrix聚合:对多个字段操作弄成矩阵


      Bucket和Metric.png

    相关性算分

    • 一些类似的这种没有啥意义的词,一般不计入算分,可以设置为停用词
    1. TF-IDF: TF表示检索词在一片文档的频率,IDF就是检索词在所有文档出现频率的log, 评分就是加权
    2. BM25: 更合理的TF-IDF计算方式,k表示词频对TF score的影响, 避免TF过大造成的影响, k1表示L对TF socore评分的影响,L表示文档长度与平均值, L越小TF score越大,越短的文章,相关性确定的越快

    高亮

    • 返回的highlight会有em标签,三种高亮介绍
    1. plain highlight默认
    2. posting highlight,index_options=offsets
      2.1 性能比plain highlight要高,因为不需要重新对高亮文本进行分词
      2.2 对磁盘的消耗更少
      2.3 将文本切割为句子,并且对句子进行高亮,效果更好
    3. fast vector highlight对于大于1M的filed,高亮性能更佳

    搜索建议

    • 两个term的相似性是如何判断的: 将搜索文本分解成token, 然后在索引字典里面找到相似term, 核心思想就是一个词改动多少可以和另一个词一样
    • 有四种
    1. term: 只基于analyze过的单个term去提供建议,并不会考虑多个term之间的关系。missing mode如索引已存在则不提供建议, popular mode推荐出现词频更高的词,always mode无论是否存在都提供建议
    2. phrase: 在第一种term上加了些逻辑,考量多个term之间关系。max errors最多可拼错多少词,confidence限制返回结果数
    3. complete: 类似自动补全功能,每发送一个字符就要查询
    4. 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, 扩大缩小主分片数
    1. 根据源索引的配置创建一个目标索引,目标索引的主分片数量是index.number_of_routing_shards的因子。这个因子需要大于源索引主分片数
    2. 然后它将源索引中的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数据。
    1. 搜索类每个节点31(尽量不要超过32G)*16= 496G,去除预留空间所以每个节点最多400G。至少需要5个节点
    2. 日志类每个节点31*50 = 1550G,2个数据节点就好
    • 磁盘容量:影响ES集群磁盘空间的有以下几点,综合考虑,留源数据的3.4倍就好
    1. 副本数量
    2. 索引开销
    3. 操作系统预留
    4. ES内部开销,比如段合并
    5. 安全预留
    建议
    • jvm堆内存不要超过物理内存的百分50
    • 可以使用协调节点进行负载
    • 关闭动态索引
    • 使用x-pack安全

    诊断

    1. 查看索引级别,找到红色索引/_cluster/health?level=indices
    2. explain变红原因, /_cluster/allocation/explain
    3. 红表示至少有一个主分片没被分配,黄表示至少有一个副本没被分配,绿是正常。集群不健康原因可能是有集群暂离了,重启之类的

    ES实践篇

    商城场景

    • es与mysql一致性处理:
    1. Canal监听数据库变更,将数据整合到ES(更新商城这种有公示期非实时,创建内容需要实时搜索到的)
    2. 同步变更到ES,相对性能不好

    参考文章

    相关文章

      网友评论

          本文标题:ElasticSearch原理与实战

          本文链接:https://www.haomeiwen.com/subject/quvealtx.html