乔叔教 Elastic - 27 - Elasticsearch 的优化技巧 (1/4) - Indexing 索引效能优化

Elasticsearch 的优化技巧 系列文章索引


前言

这系列的文章主要的目的在於当我们开始使用 Elastic Stack 时,我们如何优化 Elasticsearch 的使用方式,包含 Indexing, Searching, Disk Usage, Shard Optimization 等四个主题。

进入此章节的先备知识

  • 已经有在使用 Elasticsearch,并且了解 Elasticsearch 的基本原理与操作方式。

此章节的重点学习

  • Indexing 的效能优化的各种技巧与建议。

Indexing 索引效能优化

这篇文章主要提供 Indexing 的效能优化的各种技巧与建议:

  • Indexing 大量资料时,善用 bulk request
  • 使用 multi-thread / multi-workers 来 indexing 资料进入 Elasticsearch
  • 调低或暂时关闭 refresh_interval
  • 指定 Routing 的方式,减少 Thread 的数量
  • 第一批资料 indexing 进入 Elasticsearch 之前,先不要设定 Replica
  • 关闭 java process swapping
  • 确保 Filesystem 有足够的 memory cache
  • 使用 auto-generated ids
  • 使用更快速的储存硬体
  • 调高 indexing buffer 大小
  • 使用 cross-cluster replication 的配置让 searching 的处理不会占用 indexing 的资源
  • 调整 Translog 的 Flush 设定,减少 Disk I/O

以下会分别针对这些优化项目进行说明。

Indexing 大量资料时,善用 bulk request

大量资料要 Indexing 时,使用 bulk 减少 round-trip overhead,至於 bulk request 要多大才是合适的?这个在不同的 Elasticsearch Cluster 硬体规格、不同的 Indexing 文件大小,所以还是要依照使用情境进行 Benchmark ,找到最合适的批次处理大小,另外官方有建议,bulk request 的资料量太大的话,大量的 bulk 请求同时进入 Elasticsearch 时,可能会吃光 Elasticsearch 的记忆体,所以一般不建议一个 bulk request 处理数十 MB 以上的资料。

使用 multi-thread / multi-workers 来 indexing 资料进入 Elasticsearch

使用 multi tread/worker 来处理 indexing 绝对比单一 thraed 能提高处理的效率,不过就像 bulk request 的调效一样,这个会是依照硬体配置有不同的最佳化配置方式,所以同样的会建议进行 Benchmark 来保确当下情境下合适的 thread 数量,并注意若是 Elasticsearch 丢出 TOO_MANY_REQUESTS (429) 的错误时,就已达到上线,应该要调整配置。

调低或暂时关闭 refresh_interval

在 Elasticsearch 的 Indexing 生命周期中,当不断的有资料 indexing 进入 Elasticsearch 时,一开始是写在 memory buffer 中的,而这时还无法被搜寻到 (如下图):

image-20201012074401270

当 Elasticsearch 透过 refresh 的机制,将 In-memory buffer 的整理成 segment file,这时的状态就是能被搜寻到的 (下图中灰色的那块,因为还没进行 fsync 所以还没被 commit)。

image-20201012074416347

Elasticsearch 预设的 refresh_interval1s ,也就是一秒会进行一次处理,若是大量的资料在进行 indexing 时,可以将这个值调大,或甚至先暂时关闭,以提升 indexing 的效率。

这个配置的调整,有时能将 indexing 的效能提升一倍,不过一样是依照情境会有不一样的效果,但基本上都能有一定的成效。

这个设定的配置在 index.refresh_interval ,可参考 官方文件 - Index Module

指定 Routing 的方式,减少 Thread 的数量

当我们在 indexing 资料进入 Elasticsearch 时,Elasticsearch 的 Routing 机制预设会让资料平均分配在各个 Shard 身上,以下图为例,可以想像左边是我们的 Coordinator node,当我们有两批资料要 bulk indexing 进入 ES,而在没有特别指定 Routing 的机制,所以每个资料被分配到不同的 shard 身上,这个例子我们有 4 个 Shards,所以每一批的处理,都会要分配到 4 个 Shards,这时 bulk 的处理就会要 4 个 Threads 来处理各个 Shard 的工作,2 批 bulk request 也就是总共有 8 个 Threads。

img

如果我们指定第一批的资料只会 Routing 到 Shard 1, 2,而第二批的资料只会 Routing 到 3, 4,这样 bullk 在处理时,就只会用到 2 个 Threads来进行这样的操作。(如下图)

img

可以看到这种例子时,Threads 数量就减少一半了,这部份的配置方式,请参考 官方文件 - Routing

第一批资料 indexing 进入 Elasticsearch 之前,先不要设定 Replica

建议如果是一次性的 Indexing 一批资料进入 Elasticsearch,先将 index.number_of_replicas 设成 0,在我们 Indexing 资料时, 让 Elasticseach 把资源用在处理 Indexing ,而不要在这个阶段就去进行 Replica 的处理,等到资料都 indexing 完成之後,再把这个配置改回我们原先的预期配置,再让 Elasticseach 进行 replication 的处理。

关闭 java process swapping

为了避免 JVM heap 被 swap 到 disk,而降低 Elasticsearch 的处理效率,这边建议关闭 swapping,这部份请直接参考 官方文件 - Disable swapping

确保 Filesystem 有足够的 memory cache

Elasticsearch 使用时,由於使用 Lucene 进行许多 Segment files 的处理,会需要用到大量 filesystem 的 memory buffer,因此官方的配置建议上,会建议 JVM Heap size v.s OS filesystem 各配置 50% 的记忆体大小,因此请确保 Filesystem 拥有足够的记忆体来处理 indexing 的 request。

使用 auto-generated ids

Elasticsearch 在进行 Indexing 的处理时,会检查文件的 id 是否已存在於目前的 shard 当中,如果是使用 Elasticsearch auto-generated ids 时,由於这个 Id 的组成有包含的时间,所以 Elasticsearch 可以确保他产生时不会与现存的资料有重覆的情况,因此可以省略这个 id checking 的机制,这样会让 indexing 的速度有所提升。

使用更快速的储存硬体

Indexing 的处理是属於 I/O bound,在官方的建议配置上,会建议基本上要使用 SSD 等级的硬碟来当成 Elasticsearch 的储存硬体规格,而且使用 SSD 的配置,会让整体的 C/P 值会较高。

若是因资料量太大而有成本的考量,应该进一步再使用 Index Lifecycle Management 将 Indexing 完成的资料、或是较旧的资料,转移到较便宜的磁碟硬体状置上。

调高 indexing buffer 大小

如果有大量的 indexing 的处理时,适时的调高 indices.memory.index_buffer_size,这个值预设是 10% 的 JVM head size,这个 index buffer 是所有 active shard 共用的,所以若是有大量 indexing 处理时,也就会互相占用这个空间,所以确保 indexing 时影响的 shard 数量,并且配置足够的 index buffer size。

这个配置官方的建议是一个 shard 在 512MB 之内,若是超过的话效能一般不会有太明显的改善。

使用 cross-cluster replication 的配置让 searching 的处理不会占用 indexing 的资源

如果是持续不断的大量 indexing 资料进入 Elasticsearch 中,可以考虑使用 multi-cluster 的架构,将 indexing 的处理指向一个 Elasticsearch Cluster - A,而透过 cross-cluster replication 将资料 replica 到另一个 Elasticsearch Cluster - B,所有的 search 就指向 Elasticsearch Cluster - B,让 searching 的各种请求处理,不会占用到 indexing 的处理资源,确保 indexing 有独立不受影响的资源配置。

调整 Translog 的 Flush 设定,减少 Disk I/O

Elasticsearch 因为避免 process crash 时资料的遗失,会预设在每 5秒钟 、或是 memory size 达到 512mb …等条件达到时执行 fsync,而这个处理的 Disk I/O 成本较高,因此在大量 indexing 资料时,而且这时期又允许接受系统 crash 时资料遗失的风险,可以将 index.translog.intervalindex.translog.flush_threshold_size 的配置调高,以提升 indexing 的效率。

参考资料


查看最新 Elasticsearch 或是 Elastic Stack 教育训练资讯: https://training.onedoggo.com
欢迎追踪我的 FB 粉丝页: 乔叔 - Elastic Stack 技术交流
不论是技术分享的文章、公开线上分享、或是实体课程资讯,都会在粉丝页通知大家哦!

此系列文章已整理成书
乔叔带你上手 Elastic Stack:Elasticsearch 的最佳实践与最佳化技巧
书中包含许多的修正、补充,也依照 Elastic 新版本的异动做出不少修改。
有兴趣的读者欢迎支持! 天珑书局连结
乔叔带你上手 Elastic Stack:Elasticsearch 的最佳实践与最佳化技巧


<<:  见习村27 - First non-repeating character

>>:  Python - pandas (v) dataframe资料框

纯Javascript,使用new Date()制作date picker

刚好有一道面试题目,不能使用 input type=date 或任何现有套件,要做出类似Datepi...

【Day22】I2C Master 状态机的实现

由於上一篇已经介绍过了 SPI 的 Timing Diagram,那麽今天就直接进入 I2C Mas...

[Day26] HTB Jerry

URL : https://app.hackthebox.eu/machines/144 IP :...

[Day 26] 特徵图视觉化 Feature Map Visualization

一个模型到底学到了什麽东西一直都是一个研究课题,也是大家在意的,包括表徵学习、小样本学习、资料的偏差...

新新新手阅读 Angular 文件 - Get data from a server(3) - Day12

学习目标 本篇内容为阅读官方文件 Get data from a server 的笔记内容。 接续 ...