这是一篇转自别人的文章,真的讲的很详细。已经读了很多遍,分享给大家。
贴上原文地址(原文将了很多内容,这是优化方面摘取出来的):https://www.cnblogs.com/kevingrace/p/10682264.html
这个优化文章主要包括五部分:系统方面包括集群的部署,以及服务器环境,linux环境; 以及内存方面的优化,以及存储方面的优化;搜索的优化(读优化);还有写优化。
目录
一、Elasticserach性能优化
二、Elasticserach内存优化
三、Elasticserach存储优化
四、Elasticserach搜索速度优化
五、Elasticserach写入性能优化
一、Elasticserach性能优化
1. 硬件选择
目前公司的物理机机型在CPU和内存方面都满足需求,建议使用SSD机型。原因在于,可以快速把 Lucene 的索引文件加载入内存(这在宕机恢复的情况下尤为明显),减少 IO 负载和 IO wait以便CPU不总是在等待IO中断。建议使用多裸盘而非raid,因为 ElasticSearch 本身就支持多目录,raid 要么牺牲空间要么牺牲可用性。
2. 系统配置
ElasticSearch 理论上必须单独部署,并且会独占几乎所有系统资源,因此需要对系统进行配置,以保证运行 ElasticSearch 的用户可以使用足够多的资源。生产集群需要调整的配置如下:
1. 设置 JVM 堆大小;
2. 关闭 swap;
3. 增加文件描述符;
4. 保证足够的虚存;
5. 保证足够的线程;
6. 暂时不建议使用G1GC;
3. 设置 JVM 堆大小
ElasticSearch 需要有足够的 JVM 堆支撑索引数据的加载,对于公司的机型来说,因为都是大于 128GB 的,所以推荐的配置是 32GB(如果 JVM 以不等的初始和最大堆大小启动,则在系统使用过程中可能会因为 JVM 堆的大小调整而容易中断。 为了避免这些调整大小的暂停,最好使用初始堆大小等于最大堆大小的 JVM 来启动),预留足够的 IO Cache 给 Lucene(官方建议超过一半的内存需要预留)。
4. 关闭 swap & 禁用交换
必须要关闭 swap,因为在物理内存不足时,如果发生 FGC,在回收虚拟内存的时候会造成长时间的 stop-the-world,最严重的后果是造成集群雪崩。公司的默认模板是关闭的,但是要巡检一遍,避免有些机器存在问题。设置方法:
| 1 2 3 4 5 6 7 8 9 10 |
|
也可以通过修改 yml 配置文件的方式从 ElasticSearch 层面禁止物理内存和交换区之间交换内存,修改 ${PATH_TO_ES_HOME}/config/elasticsearch.yml,添加:
bootstrap.memory_lock: true
==========================小提示=======================
Linux 把它的物理 RAM 分成多个内存块,称之为分页。内存交换(swapping)是这样一个过程,它把内存分页复制到预先设定的叫做交换区的硬盘空间上,以此释放内存分页。物理内存和交换区加起来的大小就是虚拟内存的可用额度。
内存交换有个缺点,跟内存比起来硬盘非常慢。内存的读写速度以纳秒来计算,而硬盘是以毫秒来计算,所以访问硬盘比访问内存要慢几万倍。交换次数越多,进程就越慢,所以应该不惜一切代价避免内存交换的发生。
ElasticSearch 的 memory_lock 属性允许 Elasticsearch 节点不交换内存。(注意只有Linux/Unix系统可设置。)这个属性可以在yml文件中设置。
======================================================
5. 增加文件描述符
单个用户可用的最大进程数量(软限制)&单个用户可用的最大进程数量(硬限制),超过软限制会有警告,但是无法超过硬限制。 ElasticSearch 会使用大量的文件句柄,如果超过限制可能会造成宕机或者数据缺失。
文件描述符是用于跟踪打开“文件”的 Unix 结构体。在Unix中,一切都皆文件。 例如,“文件”可以是物理文件,虚拟文件(例如/proc/loadavg)或网络套接字。 ElasticSearch 需要大量的文件描述符(例如,每个 shard 由多个 segment 和其他文件组成,以及到其他节点的 socket 连接等)。
设置方法(假设是 admin 用户启动的 ElasticSearch 进程):
| 1 2 3 4 5 6 7 8 9 10 |
|
6. 保证足够的虚存
单进程最多可以占用的内存区域,默认为 65536。Elasticsearch 默认会使用 mmapfs 去存储 indices,默认的 65536 过少,会造成 OOM 异常。设置方法:
| 1 2 3 4 5 6 7 8 |
|
7. 保证足够的线程
Elasticsearch 通过将请求分成几个阶段,并交给不同的线程池执行(Elasticsearch 中有各种不同的线程池执行器)。 因此,Elasticsearch 需要创建大量线程的能力。进程可创建线程的最大数量确保 Elasticsearch 进程有权在正常使用情况下创建足够的线程。 这可以通过/etc/security/limits.conf 使用 nproc 设置来完成。设置方法:
| 1 2 |
|
8. 暂时不建议使用G1GC
已知 JDK 8 附带的 HotSpot JVM 的早期版本在启用 G1GC 收集器时会导致索引损坏。受影响的版本是早于 JDK 8u40 附带的HotSpot 的版本,出于稳定性的考虑暂时不建议使用。
二、Elasticserach内存优化
ElasticSearch 自身对内存管理进行了大量优化,但对于持续增长的业务仍需进行一定程度的内存优化(而不是纯粹的添加节点和扩展物理内存),以防止 OOM 发生。ElasticSearch 使用的 JVM 堆中主要包括以下几类内存使用:
1. Segment Memory;
2. Filter Cache;
3. Field Data Cache;
4. Bulk Queue;
5. Indexing Buffer;
6. Cluster State Buffer;
7. 超大搜索聚合结果集的 fetch;
1. 减少 Segment Memory
- 删除无用的历史索引。删除办法,使用 rest API
| 1 2 3 4 5 |
|
- 关闭无需实时查询的历史索引,文件仍然存在于磁盘,只是释放掉内存,需要的时候可以重新打开。关闭办法,使用 rest API
| 1 2 3 4 5 |
|
- 定期对不再更新的索引做 force merge(会占用大量 IO,建议业务低峰期触发)force merge 办法,使用 rest API
| 1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
2. Filter Cache
默认的 10% heap 设置工作得够好,如果实际使用中 heap 没什么压力的情况下,才考虑加大这个设置。
3. Field Data Cache
对需要排序的字段不进行 analyzed,尽量使用 doc values(5.X版本天然支持,不需要特别设置)。对于不参与搜索的字段 ( fields ),将其 index 方法设置为 no,如果对分词没有需求,对参与搜索的字段,其 index 方法设置为 not_analyzed。
4. Bulk Queue
一般来说官方默认的 thread pool 设置已经能很好的工作了,建议不要随意去调优相关的设置,很多时候都是适得其反的效果。
5. Indexing Buffer
这个参数的默认值是10% heap size。根据经验,这个默认值也能够很好的工作,应对很大的索引吞吐量。 但有些用户认为这个 buffer 越大吞吐量越高,因此见过有用户将其设置为 40% 的。到了极端的情况,写入速度很高的时候,40%都被占用,导致OOM。
6. Cluster State Buffer
在超大规模集群的情况下,可以考虑分集群并通过 tribe node 连接做到对用户透明,这样可以保证每个集群里的 state 信息不会膨胀得过大。在单集群情况下,缩减 cluster state buffer 的方法就是减少 shard 数量,shard 数量的确定有以下几条规则:
1. 避免有非常大的分片,因为大分片可能会对集群从故障中恢复的能力产生负面影响。 对于多大的分片没有固定限制,但分片大小为 50GB 通常被界定为适用于各种用例的限制;
2. 尽可能使用基于时间的索引来管理数据。根据保留期(retention period,可以理解成有效期)将数据分组。基于时间的索引还可以轻松地随时间改变主分片和副本分片的数量(以为要生成的下一个索引进行更改)。这简化了适应不断变化的数据量和需求;(周期性的通过删除或者关闭历史索引以减少分片)
3. 小分片会导致小分段(segment),从而增加开销。目的是保持平均分片大小在几GB和几十GB之间。对于具有基于时间数据的用例,通常看到大小在 20GB 和 40GB 之间的分片;
4. 由于每个分片的开销取决于分段数和大小,通过强制操作迫使较小的段合并成较大的段可以减少开销并提高查询性能。一旦没有更多的数据被写入索引,这应该是理想的。请注意,这是一个消耗资源的(昂贵的)操作,较为理想的处理时段应该在非高峰时段执行;(对应使用 force meger 以减少 segment 数量的优化,目的是降低 segment memory 占用)
5. 可以在集群节点上保存的分片数量与可用的堆内存大小成正比,但这在 Elasticsearch 中没有的固定限制。 一个很好的经验法则是:确保每个节点的分片数量保持在低于每 1GB 堆内存对应集群的分片在 20-25 之间。 因此,具有 32GB 堆内存的节点最多可以有 600-750 个分片;
6. 对于单索引的主分片数,有这么 2 个公式:节点数
