07.Elasticsearch参数调优
Elasticsearch参数调优
1. 系统层面的调优
系统层面的调优主要是内存的设定
与避免交换内存
。
ES 安装后默认设置的堆内存是 1GB
,这很明显是不够的,那么接下来就会有一个问题出现:我们要设置多少内存给 ES 呢?
其实这是要看我们集群节点的内存大小,还取决于我们是否在服务器节点上还是否要部署其他服务。
- 如果内存相对很大,如 64G 及以上,并且我们不在 ES 集群上部署其他服务,那么我建议 ES 内存可以设置为 31G-32G,因为这里有一个 32G 性能瓶颈问题,直白的说就是即使你给了 ES 集群大于 32G 的内存,其性能也不一定会更加优良,甚至会不如设置为 31G-32G 时候的性能。
以我调优的集群为例,我所调优的服务器节点内存为 64G,服务器节点上也基本不跑其他服务,所以我把 ES 集群内存大小设置为了 31G,以充分发挥集群性能。 - 设置 ES 集群内存的时候,还有一点就是确保堆内存最小值(Xms)与最大值(Xmx)的大小是相同的,防止程序在运行时改变堆内存大小,这是一个很耗系统资源的过程。
- 还有一点就是避免交换内存,可以在配置文件中对内存进行锁定,以避免交换内存(也可以在操作系统层面进行关闭内存交换)。对应的参数:
bootstrap.mlockall: true
2. 分片与副本
分片 (shard)
:ES 是一个分布式的搜索引擎, 索引通常都会分解成不同部分, 分布在不同节点的部分数据就是分片。ES 自动管理和组织分片, 并在必要的时候对分片数据进行再平衡分配, 所以用户基本上不用担心分片的处理细节。创建索引时默认的分片数为 5 个,并且一旦创建不能更改。副本 (replica)
:ES 默认创建一份副本,就是说在 5 个主分片的基础上,每个主分片都相应的有一个副本分片。额外的副本有利有弊,有副本可以有更强的故障恢复能力,但也占了相应副本倍数的磁盘空间。
那我们在创建索引的时候,应该创建多少个分片与副本数呢?
- 对于副本数,比较好确定,可以根据我们集群节点的多少与我们的存储空间决定,我们的集群服务器多,并且有足够大多存储空间,可以多设置副本数,一般是 1-3 个副本数,如果集群服务器相对较少并且存储空间没有那么宽松,则可以只设定一份副本以保证容灾(副本数可以动态调整)。
- 对于分片数,是比较难确定的。因为一个索引分片数一旦确定,就不能更改,所以我们在创建索引前,要充分的考虑到,以后我们创建的索引所存储的数据量,否则创建了不合适的分片数,会对我们的性能造成很大的影响。
3. 参数调优
下面我会介绍一些 ES 关键参数的调优。
有很多场景是,我们的 ES 集群占用了多大的 cpu 使用率,该如何调节呢。cpu 使用率高,有可能是写入导致的,也有可能是查询导致的,那要怎么查看呢?
可以先通过 GET _nodes/{node}/hot_threads
查看线程栈,查看是哪个线程占用 cpu
高,如果是 elasticsearch[{node}][search][T#10]
则是查询导致的,如果是 elasticsearch[{node}][bulk][T#1]
则是数据写入导致的。
在实际调优中,cpu 使用率很高,如果不是 SSD,建议把 index.merge.scheduler.max_thread_count: 1
索引 merge 最大线程数设置为 1 个,该参数可以有效调节写入的性能。因为在存储介质上并发写,由于寻址的原因,写入性能不会提升,只会降低。
还有几个重要参数可以进行设置,各位同学可以视自己的集群情况与数据情况而定。
index.refresh_interval
:这个参数的意思是数据写入后几秒可以被搜索到,默认是 1s。每次索引的 refresh 会产生一个新的 lucene 段, 这会导致频繁的合并行为,如果业务需求对实时性要求没那么高,可以将此参数调大,实际调优告诉我,该参数确实很给力,cpu 使用率直线下降。indices.memory.index_buffer_size
:如果我们要进行非常重的高并发写入操作,那么最好将indices.memory.index_buffer_size
调大一些,index buffer 的大小是所有的 shard 公用的,一般建议(看的大牛博客),对于每个 shard 来说,最多给512mb
,因为再大性能就没什么提升了。ES 会将这个设置作为每个 shard 共享的 index buffer,那些特别活跃的 shard 会更多的使用这个 buffer。默认这个参数的值是 10%,也就是 jvm heap 的 10%。translog
:ES 为了保证数据不丢失,每次 index、bulk、delete、update 完成的时候,一定会触发刷新 translog 到磁盘上。在提高数据安全性的同时当然也降低了一点性能。如果你不在意这点可能性,还是希望性能优先,可以设置如下参数:
1 | "index.translog": { |
- 这样设定的意思是开启异步写入磁盘,并设定写入的时间间隔与大小,有助于写入性能的提升。
还有一些超时参数的设置:
discovery.zen.ping_timeout
判断 master 选举过程中,发现其他 node 存活的超时设置discovery.zen.fd.ping_interval
节点被 ping 的频率,检测节点是否存活discovery.zen.fd.ping_timeout
节点存活响应的时间,默认为 30s,如果网络可能存在隐患,可以适当调大discovery.zen.fd.ping_retries ping
失败/超时多少导致节点被视为失败,默认为 3
4. 其他建议
还有一些零碎的优化建议喔。
插入索引自动生成 id
:当写入端使用特定的 id 将数据写入 ES 时,ES 会检查对应的索引下是否存在相同的 id,这个操作会随着文档数量的增加使消耗越来越大,所以如果业务上没有硬性需求建议使用 ES 自动生成的 id,加快写入速率。避免稀疏索引
:索引稀疏之后,会导致索引文件增大。ES 的 keyword,数组类型采用 doc_values 结构,即使字段是空值,每个文档也会占用一定的空间,所以稀疏索引会造成磁盘增大,导致查询和写入效率降低。
jvm调优
仅提供思路,生产环境建议给到物理机内存一半,上限32G即可
1.JVM调优策略
推荐设置是物理机的一半内存,但是当物理机的内存大于32GB的时候,若内存是64GB,则就是32GB内存。默认就是物理机内存的一半。
但是当大于64GB时,比如物理机是256GB内存,此时不应该设置内存为宿主机的一半,应该最大上限设置为32GB。
2.修改堆内存大小
1 | #查看当前内存使用状态 |
1 | #修改内存大小 |
拷贝文件到其他2个节点
1 | [root@elk01:0 ~]# scp /etc/elasticsearch/jvm.options 10.0.0.212:/etc/elasticsearch/ |
重启ES集群
1 | [root@elk01:0 ~]# systemctl restart elasticsearch |
再次查看内存占用
1 | [root@elk01:2 ~]# free -h |