Elasticsearch是目前大数据领域最热门的技术栈之一,经过近8年的发展,已从0.0.X版升级至6.X版本,虽然增加了很多的特性和功能,但是在主体架构上,还是没有太多的变化。下面就把我对于ES使用实践的一些经验总结一下,供大家参考;也请大家拍砖。
一、 硬件环境选择:
如果有条件,尽可能使用SSD硬盘, 不错的CPU。ES的厉害之处在于ES本身的分布式架构以及lucene的特性。IO的提升,会极大改进ES的速度和性能。
二、系统拓朴设计:
ES集群在架构拓朴时,一般都会采用Hot-Warm的架构模式,即设置3种不同类型的节点:Master节点、Hot 节点和 Warm节点。
Master节点设置:一般会设置3个专用的maste节点,以提供最好的弹性扩展能力。当然,必须注意discovery.zen.minimum_master_nodes 属性的设置,以防split-brain问题,使用公式设置:N/2+1(N为候选master节点数)。 该节点保持: node.data: false ; 因为master节点不参与查询、索引操作,仅负责对于集群管理,所以在CPU、内存、磁盘配置上,都可以比数据节点低很多。
Hot节点设置: 索引节点(写节点),同时保持近期频繁使用的索引。 属于IO和CPU密集型操作,建议使用SSD的磁盘类型,保持良好的写性能;节点的数量设置一般是大于等于3个。将节点设置为hot类型:
node.attr.box_type: hot
针对index, 通过设置index.routing.allocation.require.box_type: hot 可以设置将索引写入hot节点。
Warm节点设置: 用于不经常访问的read-only索引。由于不经常访问,一般使用普通的磁盘即可。内存、CPU的配置跟Hot节点保持一致即可;节点数量一般也是大于等于3个。
当索引不再被频繁查询时,可通过index.routing.allocation.require.box_type: warm, 将索引标记为warm, 从而保证索引不写入hot节点,以便将SSD磁盘资源用在刀刃上。一旦设置这个属性,ES会自动将索引合并到warm节点。同时,也可以在elasticsearch.yml中设置 index.codec: best_compression 保证warm 节点的压缩配置
Coordinating节点:协调节点用于做分布式里的协调,将各分片或节点返回的数据整合后返回。在ES集群中,所有的节点都有可能是协调节点,但是,可以通过设置node.master、node.data 、 node.ingest 都为 false 来设置专门的协调节点。需要较好的CPU和较高的内存。
三、ES的内存设置:
由于ES构建基于lucene, 而lucene设计强大之处在于lucene能够很好的利用操作系统内存来缓存索引数据,以提供快速的查询性能。lucene的索引文件segements是存储在单文件中的,并且不可变,对于OS来说,能够很友好地将索引文件保持在cache中,以便快速访问;因此,我们很有必要将一半的物理内存留给lucene ; 另一半的物理内存留给ES(JVM heap )。所以, 在ES内存设置方面,可以遵循以下原则:
1. 当机器内存小于64G时,遵循通用的原则,50%给ES,50%留给lucene。
2. 当机器内存大于64G时,遵循以下原则:
a. 如果主要的使用场景是全文检索, 那么建议给ES Heap分配 4~32G的内存即可;其它内存留给操作系统, 供lucene使用(segments cache), 以提供更快的查询性能。
b. 如果主要的使用场景是聚合或排序, 并且大多数是numerics, dates, geo_points 以及not_analyzed的字符类型, 建议分配给ES Heap分配 4~32G的内存即可,其它内存留给操作系统,供lucene使用(doc values cache),提供快速的基于文档的聚类、排序性能。
c. 如果使用场景是聚合或排序,并且都是基于analyzed 字符数据,这时需要更多的 heap size, 建议机器上运行多ES实例,每个实例保持不超过50%的ES heap设置(但不超过32G,堆内存设置32G以下时,JVM使用对象指标压缩技巧节省空间),50%以上留给lucene。
3. 禁止swap,一旦允许内存与磁盘的交换,会引起致命的性能问题。 通过: 在elasticsearch.yml 中 bootstrap.memory_lock: true, 以保持JVM锁定内存,保证ES的性能。
4. GC设置原则:
a. 保持GC的现有设置,默认设置为:Concurrent-Mark and Sweep (CMS),别换成G1GC,因为目前G1还有很多BUG。
b. 保持线程池的现有设置,目前ES的线程池较1.X有了较多优化设置,保持现状即可;默认线程池大小等于CPU核心数。如果一定要改,按公式((CPU核心数* 3)/ 2)+ 1 设置;不能超过CPU核心数的2倍;但是不建议修改默认配置,否则会对CPU造成硬伤。
四、 集群分片设置:
ES一旦创建好索引后,就无法调整分片的设置,而在ES中,一个分片实际上对应一个lucene 索引,而lucene索引的读写会占用很多的系统资源,因此,分片数不能设置过大;所以,在创建索引时,合理配置分片数是非常重要的。一般来说,我们遵循一些原则:
1. 控制每个分片占用的硬盘容量不超过ES的最大JVM的堆空间设置(一般设置不超过32G,参加上文的JVM设置原则),因此,如果索引的总容量在500G左右,那分片大小在16个左右即可;当然,最好同时考虑原则2。
2. 考虑一下node数量,一般一个节点有时候就是一台物理机,如果分片数过多,大大超过了节点数,很可能会导致一个节点上存在多个分片,一旦该节点故障,即使保持了1个以上的副本,同样有可能会导致数据丢失,集群无法恢复。所以, 一般都设置分片数不超过节点数的3倍。
五、 Mapping建模:
1. 尽量避免使用nested或 parent/child,能不用就不用;nested query慢, parent/child query 更慢,比nested query慢上百倍;因此能在mapping设计阶段搞定的(大宽表设计或采用比较smart的数据结构),就不要用父子关系的mapping。
2. 如果一定要使用nested fields,保证nested fields字段不能过多,目前ES默认限制是50。参考:
index.mapping.nested_fields.limit :50
因为针对1个document, 每一个nested field, 都会生成一个独立的document, 这将使Doc数量剧增,影响查询效率,尤其是JOIN的效率。
3. 避免使用动态值作字段(key), 动态递增的mapping,会导致集群崩溃;同样,也需要控制字段的数量,业务中不使用的字段,就不要索引。控制索引的字段数量、mapping深度、索引字段的类型,对于ES的性能优化是重中之重。以下是ES关于字段数、mapping深度的一些默认设置:
index.mapping.nested_objects.limit :10000
index.mapping.total_fields.limit:1000
index.mapping.depth.limit: 20
六、 索引优化设置:
1.设置refresh_interval 为-1,同时设置number_of_replicas 为0,通过关闭refresh间隔周期,同时不设置副本来提高写性能。
2. 修改index_buffer_size 的设置,可以设置成百分数,也可设置成具体的大小,大小可根据集群的规模做不同的设置测试。
indices.memory.index_buffer_size:10%(默认)
indices.memory.min_index_buffer_size: 48mb(默认)
indices.memory.max_index_buffer_size
3. 修改translog相关的设置:
a. 控制数据从内存到硬盘的操作频率,以减少硬盘IO。可将sync_interval的时间设置大一些。
index.translog.sync_interval:5s(默认)。
b. 控制tranlog数据块的大小,达到threshold大小时,才会flush到lucene索引文件。
index.translog.flush_threshold_size:512mb(默认)
4. _id字段的使用,应尽可能避免自定义_id, 以避免针对ID的版本管理;建议使用ES的默认ID生成策略或使用数字类型ID做为主键。
5. _all字段及_source字段的使用,应该注意场景和需要,_all字段包含了所有的索引字段,方便做全文检索,如果无此需求,可以禁用;_source存储了原始的document内容,如果没有获取原始文档数据的需求,可通过设置includes、excludes 属性来定义放入_source的字段。
6. 合理的配置使用index属性,analyzed 和not_analyzed,根据业务需求来控制字段是否分词或不分词。只有 groupby需求的字段,配置时就设置成not_analyzed, 以提高查询或聚类的效率。
七、 查询优化:
1. query_string 或 multi_match的查询字段越多, 查询越慢。可以在mapping阶段,利用copy_to属性将多字段的值索引到一个新字段,multi_match时,用新的字段查询。
2. 日期字段的查询, 尤其是用now 的查询实际上是不存在缓存的,因此, 可以从业务的角度来考虑是否一定要用now, 毕竟利用query cache 是能够大大提高查询效率的。
3. 查询结果集的大小不能随意设置成大得离谱的值, 如query.setSize不能设置成 Integer.MAX_VALUE, 因为ES内部需要建立一个数据结构来放指定大小的结果集数据。
4. 尽量避免使用script,万不得已需要使用的话,选择painless & experssions 引擎。一旦使用script查询,一定要注意控制返回,千万不要有死循环(如下错误的例子),因为ES没有脚本运行的超时控制,只要当前的脚本没执行完,该查询会一直阻塞。
如: {
“script_fields”:{
“test1”:{
“lang”:“groovy”,
“script”:“while(true){print 'don’t use script'}”
}
}
}
5. 避免层级过深的聚合查询, 层级过深的group by , 会导致内存、CPU消耗,建议在服务层通过程序来组装业务,也可以通过pipeline的方式来优化。
6. 复用预索引数据方式来提高AGG性能:
如通过 terms aggregations 替代 range aggregations, 如要根据年龄来分组,分组目标是: 少年(14岁以下) 青年(14-28) 中年(29-50) 老年(51以上), 可以在索引的时候设置一个age_group字段,预先将数据进行分类。从而不用按age来做range aggregations, 通过age_group字段就可以了。
7. Cache的设置及使用:
a) QueryCache: ES查询的时候,使用filter查询会使用query cache, 如果业务场景中的过滤查询比较多,建议将querycache设置大一些,以提高查询速度。
indices.queries.cache.size: 10%(默认),可设置成百分比,也可设置成具体值,如256mb。
当然也可以禁用查询缓存(默认是开启), 通过index.queries.cache.enabled:false设置。
b) FieldDataCache: 在聚类或排序时,field data cache会使用频繁,因此,设置字段数据缓存的大小,在聚类或排序场景较多的情形下很有必要,可通过indices.fielddata.cache.size:30% 或具体值10GB来设置。但是如果场景或数据变更比较频繁,设置cache并不是好的做法,因为缓存加载的开销也是特别大的。
c) ShardRequestCache: 查询请求发起后,每个分片会将结果返回给协调节点(Coordinating Node), 由协调节点将结果整合。
如果有需求,可以设置开启; 通过设置index.requests.cache.enable: true来开启。
不过,shard request cache只缓存hits.total, aggregations, suggestions类型的数据,并不会缓存hits的内容。也可以通过设置indices.requests.cache.size: 1%(默认)来控制缓存空间大小。
原文地址:https://blog.csdn.net/maxrocray/article/details/82257096
所有的修改都可以在elasticsearch.yml里面修改,也可以通过api来修改。推荐用api比较灵活
1.不同分片之间的数据同步是一个很大的花费,默认是1s同步,如果我们不要求实时性,我们可以执行如下:
$ curl -XPUT 'http://localhost:9200/twitter/' -d '{ "settings" : { "index" : { "refresh_interval":"60s" } } }'
此处我们是修改为60s 其实可以改为-1s 这样就是不刷新,我们需要在查询的时候进行一次索引刷新然后再查询,这个嘛就得看你们用户能容忍多少时间长度了。
2.选择正确的存储
一般来说,如果运行的是64位操作系统,你应该选择mmapfs。如果没有运行64位操作系统,为UNIX系统选择niofs,为Windows系统选择simplefs。如果你可以容忍一个易失的存储,但希望它非常快,可以看看memory存储,它会给你最好的索引访问性能,但需要足够的内存来处理所有索引文件、索引和查询。
3.优化es的线程池
cache:这是无限制的线程池,为每个传入的请求创建一个线程。
fixed:这是一个有着固定大小的线程池,大小由size属性指定,允许你指定一个队列(使用queue_size属性指定)用来保存请求,直到有一个空闲的线程来执行请求。如果Elasticsearch无法把请求放到队列中(队列满了),该请求将被拒绝。有很多线程池(可以使用type属性指定要配置的线程类型),然而,对于性能来说,最重要的是下面几个。
index:此线程池用于索引和删除操作。它的类型默认为fixed,size默认为可用处理器的数量,队列的size默认为300。
search:此线程池用于搜索和计数请求。它的类型默认为fixed,size默认为可用处理器的数量乘以3,队列的size默认为1000。
suggest:此线程池用于建议器请求。它的类型默认为fixed,size默认为可用处理器的数量,队列的size默认为1000。
get:此线程池用于实时的GET请求。它的类型默认为fixed,size默认为可用处理器的数量,队列的size默认为1000。
bulk:你可以猜到,此线程池用于批量操作。它的类型默认为fixed,size默认为可用处理器的数量,队列的size默认为50。
percolate:此线程池用于预匹配器操作。它的类型默认为fixed,size默认为可用处理器的数量,队列的size默认为1000。
elasticsearch.yml中可以设置 :
threadpool.index.type: fixed threadpool.index.size: 100 threadpool.index.queue_size: 500
当然可以restAPI设置
curl -XPUT 'localhost:9200/_cluster/settings' -d '{ "transient": { "threadpool.index.type": "fixed", "threadpool.index.size": 100, "threadpool.index.queue_size": 500 } }'
4.index过于庞大导致es经常奔溃
es最近老是挂掉,无缘无故,表现症状为 对于大小超过100g的index(5个分片 1e数据量左右)插入超级慢,由于机器资源有限 ,只能想出 将每一天的数据建立一个index+“yyyy-MM-dd” 这样可以有效缓解我们集群的压力,有人会说如果改成这种方案那么之前写的查询岂不是废了,其实很easy,es支持index通配符 比如你之前是logment 现在是logment2015-05-01和logment2015-05-02 现在只需要将查询的代码中index改为 logment* 就ok了 ,而且此法便于删除过期的index 写一个定时任务就ok了
我们日志的架构是这样的 logstash(client1) 采集日志到 redis 然后通过 logstash(client2) 从redis转至 elasticsearch ,logstash写入elasticsearch的时候默认就是按照每天来建立索引的 在其配置文件无需指明 index和type 即可。
此处会产生一个问题,就是logstash 自动建立索引的时候是根据格林尼治时间来建立的 正正比我们的时间 迟了8小时,我们需要在logstash的lib里面找到event.rb 然后找到 org.joda.time.DateTimeZone.UTC 格林尼治时间 改成 org.joda.time.DateTimeZone.getDefault() (获取本地时间类型 我这边运行就是中国/上海) 即可 话说logstash用的居然是大名鼎鼎的joda 果然是优秀程序 。
5. 采用G1垃圾回收机制代替默认CMS
这里我不分析cms和g1的细节区别,大内存(超过8g)下G1还是很给力的,亲测有效,用了G1 一周内一次FULLGC 都没有,哈哈
elasticsearch.in.sh 内 将
1
2
3
4
5
6
7
8
9
10
|
# Force the JVM to use IPv4 stack if [ "x$ES_USE_IPV4" != "x" ]; then
JAVA_OPTS= "$JAVA_OPTS -Djava.net.preferIPv4Stack=true"
fi JAVA_OPTS= "$JAVA_OPTS -XX:+UseParNewGC"
JAVA_OPTS= "$JAVA_OPTS -XX:+UseConcMarkSweepGC"
JAVA_OPTS= "$JAVA_OPTS -XX:CMSInitiatingOccupancyFraction=75"
JAVA_OPTS= "$JAVA_OPTS -XX:+UseCMSInitiatingOccupancyOnly"
|
替换为
1
2
|
JAVA_OPTS= "$JAVA_OPTS -XX:+UseG1GC"
JAVA_OPTS= "$JAVA_OPTS -XX:MaxGCPauseMillis=200"
|
大功告成
顺便说句JVM调优,调优最主要目标:1.就是降低 GC 次数时间;2.降低FULLGC 几率
PS:优化代码比优化JVM实在多了
6. 清理掉没用的缓存
回忆之前的问题发现jvm调优对于老年代的回收并没有很显著的效果,随着时间的推移内存还是不够~后来才发现是es cache的问题
其实集群建立时我们是可以调整每隔节点的缓存比例、类型、者大小的
# 锁定内存,不让JVM写入swapping,避免降低ES的性能 bootstrap.mlockall: true # 缓存类型设置为Soft Reference,只有当内存不够时才会进行回收 index.cache.field.max_size: 50000 index.cache.field.expire: 10m index.cache.field.type: soft
但是如果你不想重新配置节点并且重启,你可以做一个定时任务来定时清除cache
http://10.22.2.201:9200/*/_cache/clear //清除所有索引的cache,如果对查询有实时性要求,慎用!
到了晚上资源空闲的时候我们还能合并优化一下索引
http://10.22.2.201:9200/*/_optimize
截止现在我们es集群有38亿左右数据量,比较稳定~
相关推荐
本人在工作期间主要负责公司的集群维护与ES的分布式平台搭建,在这期间总结了自己的一套关于ES集群的优化配置的准则,性能提升有3-5倍,希望可以帮到你
【Elasticsearch 性能优化】 Elasticsearch (ES) 是一个流行的开源全文搜索引擎,用于高效存储和检索大量数据。为了实现最佳性能,我们需要对多个层面进行调优,包括集群规划、Linux 系统参数配置、JVM 参数设置...
本人在实际的工作中,负责ES平台的搭建以及维护,在实际中总结的集群优化准则,所有集群通用,性能提升有3-5倍
本文档总结了 34 道 Elasticsearch 面试题和答案,涵盖了 Elasticsearch 的基础概念、索引架构、集群管理、性能优化、倒排索引、master 选举等多个方面。 一、Elasticsearch 基础概念 1. 什么是 Elasticsearch?...
这个版本的 Elasticsearch 针对性能和稳定性进行了优化,适用于大规模数据检索和分析场景。Elasticsearch 不仅支持英文分词,还特别强调了对中文的支持,因此在处理中文文档时,它通常会搭配使用专门的中文分词器。 ...
在版本7.10.2中,Elasticsearch持续优化了性能,提升了用户体验,特别是对于MAC和LINUX系统的用户,解压即用的便捷性使得部署变得更加简单。 ### 一、分布式特性 1. **分片与副本**:Elasticsearch将数据分布在多...
Elasticsearch是一个开源的全文搜索引擎,它以其高效、可扩展的特性被广泛应用于数据分析、日志分析、网站搜索等领域。...通过理解Term和Match查询的区别,可以更好地利用Elasticsearch进行文本检索,优化搜索效果。
4. **Sharding & Replication**:Elasticsearch通过分片(Sharding)实现水平扩展,每个分片可以分布在不同的节点上,提高读写性能。同时,通过副本分片(Replica Shards)实现数据冗余和容错。 二、全文搜索引擎 ...
**Elasticsearch Analysis IK 7.10.0 分词器详解** Elasticsearch 分词器是搜索引擎核心组件之一,负责将输入的文本拆分成可搜索的独立单元——词语。在中文环境中,这个过程尤为重要,因为中文句子由多个汉字组成...
Elasticsearch的每个新版本都会带来性能优化、功能增强和问题修复。8.1.2版本可能包含了以下改进: 1. **性能提升**:通过优化内部算法和数据结构,提高了搜索、索引和查询的速度。 2. **稳定性增强**:修复了可能...
Elasticsearch的性能优化涉及多方面,包括硬件配置、内存分配、索引设置、搜索分析器调整等。合理的硬件配置(如SSD存储、足够的内存)是基础,优化索引设置(如字段类型、分析器)和搜索策略(如过滤器缓存、查询...
在本书的最后部分,作者将指导读者如何优化Elasticsearch的性能,确保其在生产环境中的高效运行。这对于负责管理Elasticsearch实例的开发者和运维人员来说至关重要。 值得注意的是,本书适合那些已经具备一定编程和...
总结来说,`elasticsearch-analysis-ik 7.17.16`为Elasticsearch提供了强大的中文分词能力,通过自定义词典、多种分词模式以及性能优化,确保了在处理中文文本时的高效和精准。在实际的文本检索应用中,合理配置和...
- **连接池管理**:支持连接池,能有效管理与Elasticsearch节点的连接,提高性能和可靠性。 - **请求构建器**:提供易于使用的API来构建复杂的Elasticsearch请求。 - **异步操作**:支持异步API调用,便于在Go的并发...
总结,"Chrome浏览器查看elasticsearch head插件"是一个实用的工具,它为Elasticsearch的管理和监控提供了便捷的Web界面,使得非开发人员也能轻松理解和操作ES集群。通过遵循正确的安装步骤,用户可以充分利用这个...
总结来说,这个压缩包提供了一套完整的 Elasticsearch 环境,包括最新的 7.14.0 版本、必备的分词器支持以及方便的可视化工具 Head 插件,配合 PHP 客户端,可以快速搭建起一个功能完备的全文搜索引擎系统。...
**Elasticsearch Head 插件详解** ...总结来说,Elasticsearch Head 插件是一款强大的工具,尤其适合开发和测试环境。通过它,我们可以轻松管理和维护 Elasticsearch 集群,提升工作效率,同时为日常运维提供了便利。
总结来说,Elasticsearch 2.4.1是一个强大且稳定的搜索和分析引擎,其分布式特性、实时性、易用的API以及丰富的功能使其成为数据存储和检索的理想选择。同时,预装的插件进一步提升了其实用性,适用于各种场景,如...
2. **版本6.2.4**:此版本是Elasticsearch的一个稳定版本,它引入了一些新特性、性能优化和修复了已知问题。例如,可能包括改进的聚合性能、对SQL查询的支持增强以及对Kibana和Logstash的集成改进。 3. **Java API*...