当前位置: 首页 > 科技观察

ElasticSearch使用规范Beta版

时间:2023-03-11 22:00:43 科技观察

本文转载自微信公众号《Redis开发与运维实战》,作者傅磊。本文转载请联系Redis开发运维实战公众号。ElasticSearch除了在日志场景(监控、数据分析、debug)等场景中大量使用之外,在过去的一年里在很多核心线上业务(比如电商业务)中大量使用。目前,有近5,000个节点。目前在db-ranking(2020-11-24)中,ElasticSearch常年位列搜索引擎第一名:很多开发同学对MySQL、Redis等存储缓存有很强的最佳实践,但对ElasticSearch的使用体验是相对的到模型。我个人的感受是ElasticSearch开发起来非常容易(比如支持动态映射),但是比较脆弱:一方面是开发同学对它的重视程度不够(比如没有自己制作)自己的映射),另一方面,它自己的一些设计(例如,聚合计算在JVM中完成)使其相对脆弱。为此,我们提供了一个关于ElasticSearch的开发规范,以帮助ElasticSearch用户减少一些可能遇到的陷阱。一、容量规划1、分片容量非日志类(搜索类、在线业务类)分片容量在10~30GB(推荐10G)日志类分片容量在30~100GB(推荐30G)文件数量在单个shard不能超过21亿(Integer.MAX_VALUE-128)注:一个shard是一个lucene片段,ES底层是基于lucene实现的。2.索引数量大索引需要拆分:提升性能,分散风险。反例:10T的索引,比如按日期和名称查询正例:index_name被拆分成多个index_name_${date}正例:index_name被hash拆分index_name_{1,2,3,...100..}提示:索引和分片越多越好,批量读写性能会下降。因此,性能和容量规划要综合考虑,结合压力测试。没有真正的最优解。3.节点、分片和索引一个节点管理的分片数量不超过200个。4.示意图(1)Cluster(2)Node:(3)Index:(4)Shard(分片)2.索引映射设计原则:无需明确默认配置和动态映射、数据使用(类型、分词、存储、排序),以下是标准映射:1.分片数量(number_of_shards):参考12.刷新频率(refresh_interval):ES的定位是一个准实时的搜索引擎。默认值为1s,表示写入后1秒后可以查找,所以这里的取值取决于业务的实时性要求。注意越小越好,刷新率越高。这意味着ES的开销也很大。通常业务类型为1-5s,日志类型为30s-120s。如果是集中导入数据,可以设置为-1,ES会自动完成数据刷新(注意完成后会改回来,否则后面会找不到数据)3.使用别名:不要依赖别名函数太多了正例:索引名称:index_name_v1别名:index_name以后会重建index_name_v2索引。对于业务,只需要更改别名即可。4.一种就够了。从ES6开始,只支持一种类型。这种类型比较鸡肋,以后的版本可能会去掉。如果一定要使用:对于已经使用了多种类型的场景,必须保证不同类型下的字段尽可能保持一致,否则会增加数据的稀疏性,影响存储和查询性能。5、慢日志(slowlog):必须配置,默认不记录慢查询,kcc提供grafana和kibana查询功能。6、一份(number_of_replicas)就够了,写多份的压力不容忽视。极端情况:如批量导入数据,可调整为0.7。字段设计(1)必须区分文本和关键字的用途:分词和关键字(判断字段是否需要分词)(2)判断字段是否需要独立存储(3)字段类型不支持修改,所以要小心。(4)对不需要聚合/排序的字段禁用doc_valuestext类型功能:分词,用于搜索。适用于:邮件内容、产品描述等需要分词全文搜索的领域;不适用:排序或聚合(SignificantTerms聚合除外)关键词类型:不分词,全段完全精确匹配。适用于:邮箱地址、地址、状态码、分类标签。(5)文本中不要做模糊搜索:8.设置合理的routingkey(默认为id),id不平衡:集群容量和访问不平衡,这对分布式存储是致命的。9.close_allES6.0已经去掉,对容量(索引过大)和性能(性能下降)都有影响。10、避免大表和宽表:ES默认最大1000,但建议不要超过100。11、不要对text类型的字段使用聚合查询。文本类型的fileddata会增加内存占用。如果有需要使用,建议使用keyword12。避免在聚合查询中使用过多的嵌套。聚合查询的中间结果和最终结果将在内存中执行。嵌套太多会导致内存耗尽比如下面的聚合嵌套了3层,country,city,salary的结果都会存入内存。如果唯一值很多,会造成内存耗尽{"aggs":{"country":{"terms":{"filed":"country","size":10},"aggs":{"city":{"terms":{"filed":"city","size":20},"aggs":{"salary":{"terms":{"filed":"salary","size":20}}}}}}}}}3.非法操作1.原则:不要忽视设计,快就是慢,不好的索引设计会后患无穷。2、拒绝大聚合:ES的计算全部在JVM内存中完成。3.拒绝模糊查询:es是大杀器{"query":{"wildcard":{"title.keyword":"*张三*"}}}4.ES获取数据时拒绝深度分页,默认为每次最多获取10000条,获取更多需要分页,但是存在深分页的问题。不要使用from/Size方法。建议使用scroll或searchAfter方法。scroll会将上一次查询结果缓存一定时间(通过配置scroll=1m实现),所以在使用scroll时一定要保证搜索结果集不要太大。5、Cardinality查询尽量不要使用cardinalityquery查询去重后的数据量(kibana中界面显示UniqueCount、DistinctCount等),即少用如下查询:"aggregations":{"cardinality":{"field":"userId"}}6.禁止查询indexName-*7。避免使用script、update_by_query、delete_by_query,对线上性能影响很大。四、常见问题解答1、索引分片数一经确定,不可更改。2.ES不支持事务性ACID特性。3、reindex:reindex可以改变索引的shard,但是代价很高:速度慢,对性能有影响,所以好的设计和规划更为重要。查询7d如下,数据量巨大,严重影响集群查询性能2.拒绝多层嵌套,不超过2层。如下图,进行了4层嵌套,每层嵌套的结果都缓存在内存中,导致内存崩溃。3.拒绝分时查询。分数查询相当于一种基于桶的聚合方法。划分的桶越多,带来的CPU计算量就越大。4.拒绝TOP>100的查询。topquery是根据聚合排序的,top太大,cpu计算量和内存消耗会造成查询瓶颈5.拒绝正则匹配查询