ElasticSearch性能调优
介绍 ElasticSearch 性能调优的一些常用参数。
1. 硬件相关
1.1 硬盘
- 一块好的硬盘,会带来 ES 整体性能 10 倍以上提升,推荐在 datanode 节点上使用 SSD 硬盘,索引的 data 目录,存放在 SSD 硬盘上。
1.2 内存
- 建议内存>128G 时,ES 使用的 JVM 内存为 30G,lucene 会消耗大量的 cache,如果索引文件很大,建议预留足够多的 cache 给 lucene 使用;
- 如果内存<64G 时,需要综合考虑单节点上索引文件的大小来评估,如果索引文件较大,建议 ES JVM 内存配置为 16G,留下足够的内存给 cache 使用;
2. 操作系统相关
2.1 调整磁盘参数
-
磁盘 blockdev 参数的 readbuffer,建议调整为 32
可以通过命令
blockdev --getra /dev/vdb
查看,需要 sudo 权限,通过命令blockdev --setra 32 /dev/vdb
进行调整;
3. ES 相关
3.1 集群相关
- 检查集群单个 datanode 节点的负载情况
- 可以通过命令
GET _cat/nodes?v
来查看,重点关注各个节点的heap.percent
和ram.percent
指标; -
heap.percent
表示 ES 使用的 JVM 内存情况,该值应该低于 75,如果长时间大于 75,表示 JVM 内存配置不够,如果 JVM 已经配置到 30G,则表示该 Datanode 节点上的压力较大,需要考虑增加 Datanode 节点来分摊压力; -
ram.percent
表示机器上内存的使用情况,实际对应 linux 上的used+cache
内存使用情况,如果该值接近 100%,则表示机器上 cache 内存不够用,主要是由于 ES 检索中,lucene 会消耗大量 cache 内存,如果 cache 不够,会导致 lucene 无法将部分文件加载到 cache 中,会频繁从磁盘中进行读取,导致查询延时加大;
- 检查集群上各个节点上的 shard 分布情况
-
可以通过命令
GET _cat/shards?v
来查看,重点关注单个 datanode 上的 shard 数量,以及 shard 的总大小;建议解决方案
-
如果 datanode 节点的压力过载,那就要设法降低 datanode 节点上的压力,主要是要降低节点上活跃的 shard 数量
- 评估索引是否在使用,关闭不用的索引
- 评估索引的副本数是否合理,降低副本数
如果只有部分 datanode 节点压力过载,可能原因是这些节点上的索引数据量较大,并且较为活跃,可以手工移动 shard 到其他压力相对较小的 datanode 上,注意手工调整前,需要先关闭集群的分片自动分配机制,调整完成后再打开;
3.2 索引相关
- 检查索引分片数
- 索引分片数不是越少越好,也不是越多越好,需要结合索引文件的大小,并发写入、查询的性能要求,进行调优,在分片数和性能之间达到一个平衡即可;
- ES 官方建议,一个分片的大小在 10-40G 之间,具体要结合索引的 mapping 复杂度来进行实际调优;
- 索引的分片数,是在索引创建的时候设置的,无法进行动态调整,如果要调整,需要通过新建索引,然后将旧索引的数据,通过 reindex 命令迁移到新索引中来进行;
- 检查索引副本数
副本数不是越多越好,副本存在的意义,最主要是保障数据的可靠性,另外可以提升查询 QPS,但是也会给集群带来翻倍的资源消耗;
建议在性能满足要求的情况下,谨慎增加副本数,没有没有特殊场景,使用默认的副本数 1 即可;
-
参考命令
curl -XPUT "http://127.0.0.1:9200/{index-name}/_settings" -H "Content-Type: application/json" -d '{ "number_of_replicas" : 0 }'
- 调整 refreshtime 参数
refreshtime 主要用于索引有写入场景时,写入的数据多久可以被检索到,refreshtime 默认为 1s,表示数据通过 bulk 接口写入后,最多 1s 后数据可以被写入到 cache 中(不是磁盘),然后就可以被检索到;
如果 ES 仅用于检索,没有写入场景,则可以将 refreshtime 设置为-1;
如果 ES 有写入场景,但是对检索实时性要求不高,可以将 refreshtime 设置为一个较大的值,比如
60s
;-
参考命令
curl -XPUT "http://127.0.0.1:9200/{index-name}/_settings" -H "Content-Type: application/json" -d '{ "refresh_interval": "60s" }'
- 调整 translog 参数
translog 存在的意义,是为了保证数据可靠性,当新写入的数据通过 refresh 刷新到 cache,还没有写到磁盘时,如果发生丢失,可以从 translog 中进行恢复,ES 中默认每 30 分钟进行一次 flush 操作,或者当 translog 的数据达到某个上限的时候会进行一次 flush 操作;
而 translog 的可靠性如何保证呢,ES 中默认是每 5s 将 synclog 写入磁盘,将这个间隔
index.translog.sync_interval
调大,可以减少磁盘 IO 的次数;另外,也可以适当调大 translog 文件多大时会自动写入磁盘的阈值,目的也是为了减少磁盘 IO 次数;-
参考命令
curl -XPUT "http://127.0.0.1:9200/index/_settings?pretty" -d '{ "index.translog.durability": "async", "index.translog.flush_threshold_size": "1gb", "index.translog.sync_interval": "30s" }
~~~ curl -XPUT '192.168.2.181:9200/index/settings?pretty' -H "Content-Type: application/json" -d '{ "index.translog.durability": "async", "index.translog.flushthresholdsize": "1gb", "index.translog.syncinterval": "30s" } ~~~
- 检查 segment 参数
- segment 表示 shard 中的分段,ES 中每次 flush,会生成一个 segment,然后再通过专门的 merge 线程,对 segment 进行 merge,在检索时,ES 会依次去每个 segment 检索,segment 越多,会导致检索效率越低;
- 通过
_cat/shards?v&h=index,shard,prirep,segmentsCount
可以查到 shard 的 segment 数量,该值越大,表示 shard 中存在的分段数量越多, - 如果索引后续不会再有大规模的写操作,建议可以通过
forcemerge
命令,对 segment 进行强制合并,可以指定合并后的 segment 数量, 但是要注意,segment 合并操作,会消耗大量的磁盘 IO,也会占用两倍于 shard 大小的磁盘空间,建议在确保磁盘空间足够的情况下,选择闲时进行 merge 操作;
阅读全文: http://gitbook.cn/gitchat/activity/5e6a2d0d34900751928d4098
您还可以下载 CSDN 旗下精品原创内容社区 GitChat App ,阅读更多 GitChat 专享技术内容哦。