如何优化Elasticsearch写入速度

62次阅读
没有评论

共计 2425 个字符,预计需要花费 7 分钟才能阅读完成。

这篇文章给大家分享的是有关如何优化 Elasticsearch 写入速度的内容。丸趣 TV 小编觉得挺实用的,因此分享给大家做个参考,一起跟随丸趣 TV 小编过来看看吧。

本次优化的示例版本是 7.9.2。ES 的版本升的是真快,已经完全脱离了 5 的时代了。

1、哪些操作占用资源

要进行优化,需要首先知道 ES 的写入过程,了解哪些步骤最耗时。

首先,就是副本 (replica) 问题,为了保证起码的高可用,这里的副本数量设置为 1,是节省不了的。所以,将副本数量设置为 0,只适合数据首次导入的时候。

如上图,一条数据想要最终落地,是需要经过多个步骤的。这个过程,甚至会有 tranlog 这样的备份机制。

ES 的底层存储是 Lucene,包含一系列的反向索引。这样的索引就成为段(segment)。但记录不会直接写入段,而是先写入一个缓冲区。

当缓冲区满了,或者在缓冲区呆的够久,达到了刷新时间(划重点),会一次性将缓冲区的内容写进段中。

这也是为什么 refresh_interval 属性的配置会严重的影响性能。如果你不要很高的实时性,不妨将其配置的大一点。

缓冲区默认使用堆空间的 10%,最小值为 48mb(针对于分片的)。如果你的索引多且写入重,这部分内存的占用是可观的,可以适当加大。

2、开始优化

数据写入,主要有三个动作:flush、refresh 和 merge。通过调整它们的行为,即可在性能和数据可靠性之间进行权衡。

flush

从上面的介绍可以看出来,translog 写入了一份全量的数据,它有点像 MysSQL 中的 binlog,或者 redis 的 aof,用来保证异常情况下的数据安全。

这是因为,我们把数据写到磁盘后,还要调用 fsync 才能把数据刷到磁盘中,如果不这样做在系统掉电的时候就会导致数据丢失。

ES 默认每次请求都进行一次 flush,但对于日志来说,这没有必要,可以将这个过程改为异步的,参数如下:

curl -H  Content-Type: application/json  -XPUT  http://localhost:9200/_all/_settings?preserve_existing=true  -d  {  index.translog.durability  :  async ,  index.translog.flush_threshold_size  :  512mb ,  index.translog.sync_interval  :  60s  }

这可以说是最重要的一步优化了,对性能的影响最大,但在极端情况下会有丢失部分数据的可能。对于日志系统来说,是可以忍受的。

refresh

除了写 translog,ES 还会将数据写入到一个缓冲区中。但是注意了! 此时,缓冲区的内容是无法被搜索到的,它还需要写入到 segment 里面才可以。

这就是 refresh 动作,默认 1 秒。也就是你写入的数据,大概率 1 秒之后才会被搜索到。

所以 ES 并不是一个实时性的搜索系统,它是一个类实时系统(near-realtime)。

通过 index.refresh_interval 可以修改这个刷新间隔。

对于日志系统来说,当然要把它调大一点啦。xjjdog 这里调整到了 120s,减少了这些落到 segment 的频率,速度自然会快。

curl -H  Content-Type: application/json  -XPUT  http://localhost:9200/_all/_settings?preserve_existing=true  -d  {  index.refresh_interval  :  120s  }

merge

merge 其实是 lucene 的机制,它主要是合并小的 segment 块,生成更大的 segment,来提高检索的速度。

原因就是 refresh 过程会生成一大堆小 segment 文件,数据删除也会产生空间碎片。所以 merge,通俗来讲就像是碎片整理进程。像 postgresql 等,也有 vaccum 进程在干同样的事。

显而易见,这种整理操作,既让费 I /O,又浪费 CPU。

要命的是,merge 有三种策略。

tiered 默认选项,它能合并大小相似的索引段,并考虑每层允许的索引段的最大个数。

log_byte_size 以字节数的对数为计算单位,选择多个索引来合并创建新索引。

log_doc 以索引段的文档数量为计算单位,选择多个索引来合并创建新索引。

每一种策略都有非常详细的针对性配置,在此不啰嗦。

由于日志系统并没有随机性的删除操作,所以我们保持默认就可以。

3、微调

新版本对线程池的配置进行了优化,不需要配置复杂的 search、bulk、index 线程池。有需要配置下面几个就行了:thread_pool.get.size,  thread_pool.write.size, thread_pool.listener.size,  thread_pool.analyze.size。具体可观测_cat/thread_pool 接口暴露的数据进行调整。

其实,可以通过配置多块磁盘的方式,来分散 I / O 的压力,但容易会造成数据热点集中在单块磁盘上。

Lucene 的索引建立过程,非常耗费 CPU,可以减少倒排索引的数量来减少 CPU 的损耗。第一个优化就是减少字段的数量; 第二个优化就是减少索引字段的数量。具体的操作,是将不需要搜索的字段,index 属性设置为 not_analyzed 或者 no。至于_source 和_all,在实际调试中效果不大,不再赘述。

另外,如果日志是通过 filebeat 或者 logstash 这样的组件传导过来的,一般都是开启了批量模式。通过批量能够增加性能,但也不宜过大,可根据实际观测进行设置,一般 1k-1w 之间都是可以的。

感谢各位的阅读!关于“如何优化 Elasticsearch 写入速度”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-08-16发表,共计2425字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)