点击上方“方志朋”,选择“设为星标”

做积极的人,而不是积极废人

Elasticsearch常常作为日志存储和分析的工具,在企业级应用中常常使用。Elasticsearch提供强大的搜索、分析功能,已经是后端技术栈不可缺少的一部分。
在维护ElastciSearch集群的时候,对Elasticsearch进行了一些调优和分析,现整理成文,纯属拙见,如果有不合理之处,欢迎指出探讨。我所使用的Elasticsearch版本为5.x。

文件句柄优化

Elasticsearch有大量的查询数据和插入数据的请求,需要大量文件句柄,centos系统默认的1024个文件句柄。如果文件句柄用完了,这就意味着操作系统会拒绝连接,意味着数据可能丢失,这是灾难性的后果,
不能被接受。登陆Elasticsearch的启动用户,用一下命令查看:

ulimit -a

查看结果:

core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 127673
max locked memory       (kbytes, -l) unlimited
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 2056474
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

上面的文件句柄(open files)的个数为1024,在ElasticSearch大量请求的情况下,这个句柄数量是不够的,可以改成655360。

临时修改可以通过执行以下命令,即可立即生效,但是机器重启后又会失效:

ulimit -n 655360

永久生效,修改/etc/security/limits.conf,需要重启机器生效:

u_es - nofile 655360

上述配置中u_es为启动ElasticSearch的用户,设置了该用户的ElasticSearch的文件句柄为655360、

JVM参数优化

Elasticsearch是运行在JVM上的,对其做JVM参数调优至关重要。最常见的调优是Java内存的分配。下面是JVM的内存模型,具体每块的作用,不在这里阐述。

新生代和老年代分配的内存比例给多大?

Jvm内存分为新生代和老年代。

  • 新生代(或者伊甸园)
    新实例化的对象分配的空间。新生代空间通常都非常小,一般在 100 MB–500 MB。新生代也包含两个 幸存 空间。

  • 老年代
    较老的对象存储的空间。这些对象预计将长期留存并持续上很长一段时间。老生代通常比新生代大很多。

新生代、老生代的垃圾回收都有一个阶段会“stop the world”。在这段时间里,JVM 停止了程序运行,以便对对象进行可达性分析,收集死亡对象。在这个时间停止阶段,一切都不会发生。请求不被服务,ping 不被回应,分片不被分配。整个世界都真的停止了。
对于新生代,这不是什么大问题;那么小的空间意味着 GC 会很快执行完。但是老生代大很多,而这里面一个慢 GC 可能就意味着 1 秒乃至 15 秒的暂停——对于服务器软件来说这是不可接受的。

那一般我们给新生代和老年代分配多大的内存呢?他们的比例是多少呢?
一般来说,老年代和新生代的内存比例为2:1是比较合适的。比如给堆内存分配3G,则新生代分配1G,其余都给老年代。在ElasticSearce的配置文件jvm.options文件配置:

-Xms3g  //配置堆初始化大小
-Xmx3g   //配置堆的最大内存
-Xmn1g   //配置新生代内存。

该分配多大的内存给Elasticesearch?

在使用Elasticesearch的时候,我们对装Elasticesearch的机器进行了升级,从最小的8G内存升级到了16G内存,然后到目前的32G内存。一台机器装一个Elasticesearch节点,我们应该怎么分配机器的内存呢?
官方给出了解决方案,把一半(少于)的内存分配给Luence,另外的内存分配给ElasticSearch.

内存对于 Elasticsearch 来说绝对是重要的,它可以被许多内存数据结构使用来提供更快的操作。但是说到这里, 还有另外一个内存消耗大户 非堆内存 (off-heap):Lucene。

Lucene 被设计为可以利用操作系统底层机制来缓存内存数据结构。Lucene 的段是分别存储到单个文件中的。因为段是不可变的,这些文件也都不会变化,这是对缓存友好的,同时操作系统也会把这些段文件缓存起来,以便更快的访问。

Lucene 的性能取决于和操作系统的相互作用。如果你把所有的内存都分配给 Elasticsearch 的堆内存,那将不会有剩余的内存交给 Lucene。这将严重地影响全文检索的性能。

标准的建议是把 50% 的可用内存作为 Elasticsearch 的堆内存,保留剩下的 50%。当然它也不会被浪费,Lucene 会很乐意利用起余下的内存。

我们实际的解决办法是将机器的一半分给Elasticesearch的堆,栈内存、方法区、常量池、非堆内存占用另外一半。

分配给堆最大内存应该小于 32766 mb(~31.99 gb)

JVM 在内存小于 32 GB 的时候会采用一个内存对象指针压缩技术。

对于 32 位的系统,意味着堆内存大小最大为 4 GB。对于 64 位的系统, 可以使用更大的内存,但是 64 位的指针意味着更大的浪费,因为你的指针本身大了。更糟糕的是, 更大的指针在主内存和各级缓存(例如 LLC,L1 等)之间移动数据的时候,会占用更多的带宽。

Java 使用一个叫作 内存指针压缩(compressed oops)的技术来解决这个问题。它的指针不再表示对象在内存中的精确位置,而是表示 偏移量 。这意味着 32 位的指针可以引用 40 亿个 对象 , 而不是 40 亿个字节。最终, 也就是说堆内存增长到 32 GB 的物理内存,也可以用 32 位的指针表示。

一旦你越过那个神奇的 ~32 GB 的边界,指针就会切回普通对象的指针。每个对象的指针都变长了,就会使用更多的 CPU 内存带宽,也就是说你实际上失去了更多的内存。事实上,当内存到达 40–50 GB 的时候,有效内存才相当于使用内存对象指针压缩技术时候的 32 GB 内存。

这段描述的意思就是说:即便你有足够的内存,也尽量不要 超过 32 GB。因为它浪费了内存,降低了 CPU 的性能,还要让 GC 应对大内存。

关掉swap

内存交换 到磁盘对服务器性能来说是 致命 的。

如果内存交换到磁盘上,一个 100 微秒的操作可能变成 10 毫秒。再想想那么多 10 微秒的操作时延累加起来。不难看出 swapping 对于性能是多么可怕。

用以下命令关掉swap:

sudo swapoff -a

不要碰以下的配置

所有的调整就是为了优化,但是这些调整,你真的不需要理会它。因为它们经常会被乱用,从而造成系统的不稳定或者糟糕的性能,甚至两者都有可能。

线程池配置

许多人 喜欢 调整线程池。无论什么原因,人们都对增加线程数无法抵抗。索引太多了?增加线程!搜索太多了?增加线程!节点空闲率低于 95%?增加线程!
Elasticsearch 默认的线程设置已经是很合理的了。对于所有的线程池(除了 搜索 ),线程个数是根据 CPU 核心数设置的。如果你有 8 个核,你可以同时运行的只有 8 个线程,只分配 8 个线程给任何特定的线程池是有道理的。
搜索线程池设置的大一点,配置为 int(( 核心数 * 3 )/ 2 )+ 1 。

垃圾回收器

Elasticsearch 默认的垃圾回收器( GC )是 CMS。这个垃圾回收器可以和应用并行处理,以便它可以最小化停顿。然而,它有两个 stop-the-world 阶段,处理大内存也有点吃力。

尽管有这些缺点,它还是目前对于像 Elasticsearch 这样低延迟需求软件的最佳垃圾回收器。官方建议使用 CMS。

合理设置最小主节点

minimum_master_nodes 设置及其重要,为了防止集群脑裂,这个参数应该设置为法定个数就是 ( master 候选节点个数 / 2) + 1。

分片均匀,磁盘优化,剔除掉高负载的Master竞选?

笔者在实际生产环境中遇到了有一个节点的负载是其他节点的几倍,从虚拟机监控上看,所有的节点的qps是差不多的。机器的配置是一样的,为什么负载会有如此大的差距?

  • 首先,我们怀疑数据分配不均匀,我们排查了下,没有这种现象。

  • 然后,我们监控到了高负载的节点磁盘IO非常的高,经常达到100%,我们怀疑是那个虚拟机磁盘性能不行。但是我们当时没有更好的磁盘。

  • 我们找到了一个适中的解决办法是将这台高负载的节点剔除Master竞选,即将elasticsearch.yml文件中的node.master改为false然后重启,负载下降了一些。

数据存储天数的优化

存储天数的优化,这个需要根据实际的业务来,下面是删除过期数据的脚本,该脚本来源于https://stackoverflow.com/questions/33430055/removing-old-indices-in-elasticsearch#answer-39746705  ;

#!/bin/bash
searchIndex=logstash-monitor
elastic_url=logging.core.k94.kvk.nl
elastic_port=9200date2stamp () {date --utc --date "$1" +%s
}dateDiff (){case $1 in-s)   sec=1;      shift;;-m)   sec=60;     shift;;-h)   sec=3600;   shift;;-d)   sec=86400;  shift;;*)    sec=86400;;esacdte1=$(date2stamp $1)dte2=$(date2stamp $2)diffSec=$((dte2-dte1))if ((diffSec < 0)); then abs=-1; else abs=1; fiecho $((diffSec/sec*abs))
}for index in $(curl -s "${elastic_url}:${elastic_port}/_cat/indices?v" |     grep -E " ${searchIndex}-20[0-9][0-9]\.[0-1][0-9]\.[0-3][0-9]" | awk '{     print $3 }'); dodate=$(echo ${index: -10} | sed 's/\./-/g')cond=$(date +%Y-%m-%d)diff=$(dateDiff -d $date $cond)echo -n "${index} (${diff})"if [ $diff -gt 1 ]; thenecho " / DELETE"# curl -XDELETE "${elastic_url}:${elastic_port}/${index}?pretty"elseecho ""fi
done

然后使用crontab每天定时执行一次这个脚本。

集群分片设置

ES一旦创建好索引后,就无法调整分片的设置,而在ES中,一个分片实际上对应一个lucene 索引,而lucene索引的读写会占用很多的系统资源,因此,分片数不能设置过大;所以,在创建索引时,合理配置分片数是非常重要的。一般来说,我们遵循一些原则:

  1. 控制每个分片占用的硬盘容量不超过ES的最大JVM的堆空间设置(一般设置不超过32G,参加上文的JVM设置原则),因此,如果索引的总容量在500G左右,那分片大小在16个左右即可;当然,最好同时考虑原则2。

  2. 考虑一下node数量,一般一个节点有时候就是一台物理机,如果分片数过多,大大超过了节点数,很可能会导致一个节点上存在多个分片,一旦该节点故障,即使保持了1个以上的副本,同样有可能会导致数据丢失,集群无法恢复。所以, 一般都设置分片数不超过节点数的3倍。

索引优化

1.修改index_buffer_size 的设置,可以设置成百分数,也可设置成具体的大小,大小可根据集群的规模做不同的设置测试。

indices.memory.index_buffer_size:10%(默认)
indices.memory.min_index_buffer_size:48mb(默认)
indices.memory.max_index_buffer_size
  1. _id字段的使用,应尽可能避免自定义_id, 以避免针对ID的版本管理;建议使用ES的默认ID生成策略或使用数字类型ID做为主键。

  2. _all字段及_source字段的使用,应该注意场景和需要,_all字段包含了所有的索引字段,方便做全文检索,如果无此需求,可以禁用;_source存储了原始的document内容,如果没有获取原始文档数据的需求,可通过设置includes、excludes 属性来定义放入_source的字段。

  3. 合理的配置使用index属性,analyzed 和not_analyzed,根据业务需求来控制字段是否分词或不分词。只有 groupby需求的字段,配置时就设置成not_analyzed, 以提高查询或聚类的效率。

查询优化

  • 查询优化,调整filter过滤顺序

如果把过滤效果不明显的条件放在了前面,导致查询出大量不需要的数据,导致查询变慢。
把过滤效果明显的条件提前,按照过滤效果把过滤条件排序

  • 索引时间精度优化

研究Filter的工作原理可以看出,它每次工作都是遍历整个索引的,所以时间粒度越大,对比越快,搜索时间越短,在不影响功能的情况下,时间精度越低越好,有时甚至牺牲一点精度也值得,当然最好的情况是根本不作时间限制。
es重新刷索引,增加冗余的时间字段,精确到天。带有时间范围的查询使用该字段进行查询

  • 查询Fetch Source优化

业务查询语句获取的数据集比较大,并且从source中获取了非必须的字段,导致查询较慢。
举例:只需要从es中查询id这一个字段,却把所有字段查询了出来

  • 预索引数据

利用索引查询数据是最优的方式。例如,如果所有的文档都有 price 字段,并且大多数查询都在一个固定的范围列表中运行范围聚合,那么可以通过将 index 预索引到 index 和使用 terms 聚合来更快地实现聚合。

例如,像下面这样:

PUT index/type/1
{"designation": "spoon","price": 13
}

像这样的查询:

GET index/_search
{"aggs": {"price_ranges": {"range": {"field": "price","ranges": [{ "to": 10 },{ "from": 10, "to": 100 },{ "from": 100 }]}}}
}

文档在索引的时候要使用 price_range ,应该被映射为关键词:

PUT index
{"mappings": {"type": {"properties": {"price_range": {"type": "keyword"}}}}
}PUT index/type/1
{"designation": "spoon","price": 13,"price_range": "10-100"
}

然后这个请求就直接聚合新字段,而不是在 price 字段运行范围查询:

GET index/_search
{"aggs": {"price_ranges": {"terms": {"field": "price_range"}}}
}

总结

总的来说,ElasticSearch的优化,优化可以从以下方面的考虑:

  • 硬件的优化:机器分配,机器配置,机器内存,机器CPU,机器网络,机器磁盘性能

  • 操作系统设置优化:文件句柄优化、swap关闭

  • ElasticSearch合理分配节点,合理分配参加竞选Master的节点

  • ElasticSearch的存储的优化,副本数量、索引数量、分片数量

  • ElasticSearch的使用优化,索引的优化,查询的优化

参考资料

https://www.elastic.co/guide/cn/elasticsearch/guide/current/_monitoring_individual_nodes.html

https://www.elastic.co/guide/cn/elasticsearch/guide/current/heap-sizing.html

https://www.fangzhipeng.com/javainterview/2019/04/09/jmm.html

https://www.elastic.co/guide/cn/elasticsearch/guide/current/important-configuration-changes.html

https://stackoverflow.com/questions/33430055/removing-old-indices-in-elasticsearch#answer-39746705

https://zhuanlan.zhihu.com/p/43437056

http://doc.codingdict.com/elasticsearch/497/

热门内容:   

  • 为什么说「中台」程序员未来会最值钱?

  • Java分布式 RPC 框架性能大比拼,Dubbo最差?

  • 如何使用BigDecimal?

  • 面试官:MySQL 表设计要注意什么?

  • 面试官问:平时碰到系统CPU飙高和频繁GC,你会怎么排查?

  • Java 线程池 ThreadPoolExecutor 八种拒绝策略浅析

  • Spring Boot 实现定时任务的 4 种方式

  • Java 程序员常用资源工具集合(建议收藏)

最近面试BAT,整理一份面试资料《Java面试BAT通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。

获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

明天见(。・ω・。)ノ♡

Elasticsearch使用优化之拙见相关推荐

  1. ElasticSearch性能优化策略【转】

    ElasticSearch性能优化主要分为4个方面的优化. 一.服务器部署 二.服务器配置 三.数据结构优化 四.运行期优化 一.服务器部署 1.增加1-2台服务器,用于负载均衡节点 elasticS ...

  2. 【es】将 elasticsearch 写入速度优化到极限

    1.概述 转载:将 elasticsearch 写入速度优化到极限 基于版本: 2.x – 5.x 在 es 的默认设置,是综合考虑数据可靠性,搜索实时性,写入速度等因素的,当你离开默认设置,追求极致 ...

  3. elasticsearch 性能优化

    所有的修改都可以在elasticsearch.yml里面修改,也可以通过api来修改.推荐用api比较灵活 1.不同分片之间的数据同步是一个很大的花费,默认是1s同步,如果我们不要求实时性,我们可以执 ...

  4. 美团外卖搜索基于Elasticsearch的优化实践

    美团外卖搜索工程团队在Elasticsearch的优化实践中,基于Location-Based Service(LBS)业务场景对Elasticsearch的查询性能进行优化.该优化基于Run-Len ...

  5. Elasticsearch性能优化实战指南

    点击上方"方志朋",选择"设为星标" 做积极的人,而不是积极废人 0.背景 在当今世界,各行各业每天都有海量数据产生,为了从这些海量数据中获取想要的分析结果,需 ...

  6. ElasticSearch 性能优化实战,让你的 ES 飞起来!

    点击上方"朱小厮的博客",选择"设为星标" 回复"1024"获取独家整理的学习资料 ES发布时带有的默认值,可为es的开箱即用带来很好的体验 ...

  7. 干货!Elasticsearch性能优化实战指南

    点击上方"朱小厮的博客",选择"设为星标" 回复"1024"获取独家整理的学习资料 0.背景 在当今世界,各行各业每天都有海量数据产生,为了 ...

  8. Elasticsearch 写入优化记录,从3000到8000/s

    点击关注公众号,实用技术文章及时了解 来源:blog.csdn.net/wmj2004/article/ details/80804411 背景 基于elasticsearch-5.6.0 机器配置: ...

  9. elasticsearch配置优化

    http://m.blog.csdn.net/article/details?id=50330149 节点 Elasticsearch 节点有四种 : master and data--- 默认是这种 ...

最新文章

  1. hls二次加密 m3u8_HLS实战之Wireshark抓包分析
  2. 在Rails中撤消脚手架
  3. Python编程4道练习题
  4. aes子密钥生成c语言_HBase配置AES加密
  5. softlockup检测(watchdog)原理(用于检测系统调度是否正常)
  6. DOD,与cisco三层模型
  7. reimage repair-打开网页总是自动跳转要你下reimage repair
  8. Adding Powers
  9. 网络冗余备份之浮动路由
  10. css中表格内容从顶部开始,CSS粘性定位固定表格thead部分元素小方法
  11. 启发式算法(Heuristic Algorithm)
  12. 获取mp3部分信息的python代码
  13. Google Play 应用上架流程(2020版)
  14. Http——超文本传输协议
  15. Openlayers之地图比例尺控件
  16. 【个人向】《春物》 小说原文关键段落摘录
  17. 【UML 建模】在线UML建模工具 ProcessOn 使用具体解释
  18. android studio运行时报错AVD Nexus_5X_API_P is already running解决办法
  19. Cocos2d-x 游戏中子弹的设计 (一)
  20. 计算机学猫叫音乐,抖音学猫叫音乐 抖音学猫叫什么歌

热门文章

  1. 【Java】身份证号码验证
  2. Web App、Hybrid App与Native App的设计差异
  3. 【第22周复盘】可以查成绩了!
  4. Matlab编程与数据类型 -- 内联函数
  5. 深圳杯---垃圾焚烧厂的经济补偿问题
  6. 英特尔携手中科院计算所建立中国首个 oneAPI 卓越中心
  7. 10年IT老兵给新人程序员的几点建议
  8. Python + 爬虫:可视化大屏帮你选粽子
  9. 猖狂!微软、思科源码惨遭黑客 100 万美元打包出售
  10. B 站神曲damedane:精髓在于换脸,五分钟就能学会