在工作中 ElasticSearch 的一些使用规范

前言

大家好,我是路由器没有路

今天跟大家聊下自己在工作中总结的关于使用 ElasticSearch 的一些规范,如有不当的地方,欢迎指正。

Elasticsearch 是一个基于 Lucene 的搜索引擎,支持分布式搜索、多租户、实时搜索和分析等能力,具有高效、稳定、可扩展的优势,被广泛应用于企业级搜索和数据分析场景。

关于 ElasticSearch 的介绍,这里不再赘述了,有兴趣的同学可以看下我前面写的一篇文章:Elasticsearch 的简单介绍和如何使用

基础配置规划

分片(shard)容量

  • 非日志型(搜索型、线上业务型)的 shard 容量在 20~40GB(建议在 20G)
  • 日志型的 shard 容量在 35~100GB(建议 35G)
  • 单个 shard 的文档个数不能超过 20 亿左右(Integer.MAX_VALUE – 128)

注:一个 shard 就是一个 lucene 分片,ES 底层基于 lucene 实现。

索引(index)数量

大索引需要拆分:提高性能,降低风险,将风险分散化。

反例:例如一个 10 多 T 的索引,按 date 查询、name 查询

正例:indexname 拆成多个 index_name${date}

正例:indexname 按 hash 拆分 index_name{1,2,3,…100..}

节点、分片、索引

一个节点管理的 shard 数不要超过 200 个

索引 mapping 的设计原则

大原则:不使用默认配置和动态 mapping、数据用途(类型、分词、存储、排序)弄清,下面是一个标准 mapping

{


  "aliases": {
    "my_index_name": {}
  },
  "settings": {
    "index": {
      "refresh_interval": "1s",
      "number_of_shards": "12",
      "number_of_replicas": "1",
      "search.slowlog.threshold.query.warn": "5s",
      "search.slowlog.threshold.query.info": "1s",
      "search.slowlog.threshold.fetch.warn": "1s",
      "search.slowlog.threshold.fetch.info": "800ms",
      "indexing.slowlog.threshold.index.warn": "12s",
      "indexing.slowlog.threshold.index.info": "2s"
    }
  },
  "mappings": {
    "_default_": {
      "_all": {
        "enables": false
      }
    },
    "my_type_name": {
      "properties": {
        "xxx_id": {
          "type": "keyword"
        },
        "timestamp": {
          "type": "long"
        },
        "xxx_status": {
          "type": "integer"
        },
        "xxx_content": {
          "type": "ztext"
        }
      }
    }
  }
}

refresh 频率(refresh_interval)

ES 的定位是准实时搜索引擎,该值默认是 1s,表示写入后 1 秒后可被搜索到,所以这里的值取决于业务对实时性的要求。

注意这里并不是越小越好,刷新频率高也意味着对 ES 的开销也大,通常业务类型在 1-5s,日志型在 30s-120s,如果集中导入数据可将其设置为-1,ES 会自动完成数据刷新(注意完成后更改回来,否则后续会出现搜索不到数据)。

别名(aliases)

记住:在某些场景下可使用别名,但不要过度依赖别名功能。

正例

索引名:index_name_v1

别名:index_name

未来重建 index_name_v2 索引,对于业务来说只需要换别名。

type 个数

1 个就够了,从 ES6 开始只支持一个 type,这个 type 比较鸡肋,后面的版本可能会去掉。

如果一定用:针对已经使用多个 type 的场景,一定要保证不同 type 下字段尽量保持一致,否则会加大数据稀疏性,存储与查询性能受影响

慢日志(slowlog)

一定要配置,默认不记录慢查询,kcc 提供了 grafana、kibana 查询功能。

副本(number_of_replicas)

1 个就够用,副本多写入压力不可忽视。极端情况下:譬如批量导入数据,可以将其调整为 0。

字段设计

  • textkeyword 的用途必须分清:分词和关键词(确定字段是否需要分词)
  • 确定字段是否需要独立存储
  • 字段类型不支持修改,必须谨慎
  • 对不需要进行聚合/排序的字段禁用 doc_values
  • 不要在 text 做模糊搜索

text 类型:适用于分词用于搜索,适用于 email 、内容、描述等需要分词的全文检索,不适用聚合。

keyword 类型:无需分词,整段完整精确匹配,适用于:email 、地址、状态码、分类 tags。

设置合理的 routing key(默认是 id)

id 不均衡:集群容量和访问不均衡,对于分布式存储是致命的。

关闭 _all

ES6.0 已经去掉,对容量(索引过大)和性能(性能下降)都有影响。

避免大宽表:

ES 默认最大 1000,但建议不要超过 100

text 类型的字段不要使用聚合查询

text 类型 fileddata 会加大对内存的占用,如果有需求使用,建议使用 keyword

聚合查询避免使用过多嵌套,

聚合查询的中间结果和最终结果都会在内存中进行,嵌套过多,会导致内存耗尽。

以下是聚合就嵌套了 3 层,结果都会保存在内存中,

如果唯一值较多,就会导致内存耗尽:

{


  "aggs": {
    "country": {
      "terms": {
        "filed": "country",
        "size": 10
      },
      "aggs": {
        "city": {
          "terms": {
            "filed": "city",
            "size": 20
          },
          "aggs": {
            "salary": {
              "terms": {
                "filed": "salary",
                "size": 20
              }
            }
          }
        }
      }
    }
  }
}

谨慎操作

  1. 原则:不要忽略设计,快就是慢,坏的索引设计后患无穷.

  2. 拒绝大聚合 :ES 计算都在 JVM 内存中完成。

  3. 拒绝模糊查询:es 一大杀手

    wildcard 搜索

    {
    
    
      "query": {
        "wildcard": {
          "title.keyword": "*张三*"
        }
      }
    }
    
  4. 拒绝深度分页 ES 获取数据时,每次默认最多获取 10000 条,获取更多需要分页,但存在深度分页问题,一定不要使用 from/Size 方式,建议使用 scroll 或者 searchAfter 方式。

    scroll 会把上一次查询结果缓存一定时间(通过配置 scroll=1m 实现),所以在使用 scroll 时一定要保证 search 结果集不要太大。

  5. 基数查询 尽量不要用基数查询去查询去重后的数据量大小(kibana 中界面上显示是 Unique Count,Distinct Count 等)

    即少用以下查询:

    "aggregations": {
        "cardinality": {
            "field": "userId"
        }
    }
    
  6. 禁止查询 indexName-*

  7. 避免使用 scriptupdate_by_querydelete_by_query,对线上性能影响较大。

需注意的问题

  1. 一个索引的 shard 数一旦确定不能改变
  2. ES 不支持事务 ACID 特性。
  3. reindex: reindex 可以实现索引的 shard 变更,但代价非常大:速度慢、对性能有影响,所以好的设计和规划更重要

总结

以上是自己在工作中总结的关于 ElasticSearch 的使用规范,如对你有帮助,可以给个赞。

另外,Elasticsearch 的使用需要结合实际业务场景,通过优化和管理来提高其性能和稳定性,我们需要根据特定的业务场景和使用需求来选择合适的方案。

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MY5uz9rA' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片