Elasticsearch 的优化技巧 系列文章索引
这系列的文章主要的目的在於当我们开始使用 Elastic Stack 时,我们如何优化 Elasticsearch 的使用方式,包含 Indexing, Searching, Disk Usage, Shard Optimization 等四个主题,这篇以是 Shard Optimization 为主的介绍。
为了避免机器毁损时造成资料的遗失以及提升 indexing 或是 searching 的资料处理能力,Elasticsearch Cluster 在多个 nodes 并包含多个 shards 的分散式资料架构中,储存 index 资料和这些资料的 replica,但是这些 shards 的数量,以及 replica 的数量,对於 cluster 的健康状态及效能其实有很大的影响,最常遇到的一个问题就是 oversharding
(过多的分片),而这种 shard 数量太多的状况可能会影响到 cluster 的稳定性,因此在管理 Elasticsearch Cluster 时,最好先了解你的资料,并规划好 Sharding Strategy ,以下是规划时建议要考量的项目。
底下分别是这些建议的个别说明。
大多数的 searching 在执行时,查询的资料是会横跨多个 shards,而每个 shard 在搜寻时会使用一个 CPU thread 在处理执行,也就是:
一个 Node 依照不同的功能分类有多种 Thread pool, 其中 search (count/search/suggest) 的 size 是
int((# of allocated processors * 3) / 2) + 1
并且 queue_size 预设是1000
,而 write (index/delete/update/bulk) 的 size 是# of allocated processors
,预设的 queue_size 也是1000
。( 官方文件 - Thread pools )
每个 Shard 固定都会占用一些 CPU 和 Memory 的资源,以同样的资料量,Shard 数量愈多,overhead 也就愈高,占用的总系统资源也会较多一些。
Shard 的另外的资源成本有一部份会是里面的 sgement files,segment files 的 metadata 会被存放在 JVM heap memory 中,以提供搜寻时处理的加速,而 segment files 在经过 merge 後,也会将已标示为删除的资料给移除,加上 segment files 数量变少,占用的 heap memeory 也会较少。
预设是自动分配,而 Elasticsearch 也就会尽可能的平均分配,而我们可以使用 shard allocation awareness 的机制来自己决定 shard 被分配的规则,并依照业务的需求来分配不同等级的硬体给不同的资料。
如果是 time-based 的资料,也可以把时间较旧、使用率较低的资料,分配到较次等的硬体上,以优化储存硬体的成本,这部份也可以参考 Hot-Warm-Cold architecture 的运作机制来处理。
Document 的删除,在 Elasticsearch 的运作上,是产生另外一笔 "标示删除" 的记录在 segment files 中,所以这些都还是会持续的占用系统资源,一直到 segment merge 之後,才会真正的被移除。
因此如果会周期性的删除一批旧资料时,最好能以 Index 为单位来删除,而不是透过 delete_by_query 之类的批次删除机制。
Index Lifecycle Management 里面可以定义 自动 Rollover 的机制,也就是当资料量成长到 某个数量、某个时间、某个大小 时,会自动产生新的 Index 来放新的资料,而太旧的资料也能设定自动删除。
使用 ILM 是个很好来管理 Shard Strategy 的工具,因为他能很轻易的进行策略的调整:
Shard 太大时,会让 Cluster 进行 shard recover 时的成本太高。例如一个 node 死掉时,Cluster 会尝试进行 rebalance ,这时要将某个 node 身上的 shard 搬到另一个 node 时,这个搬家所消耗的频宽与处理的系统资源都会是成本。
不过这个还是要依照 Cluster 的硬体规格及 Node 的数量来进行全面的评估。
一个 node 能处理的 shard 数量大约会和 JVM heap memory 大小成一定的比例,以官方统计的数字,一般是每 GB 的 heap memory 大约可以处理 20 个 shards,也就是 30GB 的 heap memory 可以处理 600 个 shards,不过这同样的还是要依照 Elasticsearch Cluster 的硬体规格与使用状况来评估。
若要查看 shard 数量,可以从 _cat API 来看
GET _cat/shards
当我们将一个 Index 设定有多个 primary shard 时,主要的目的就是为了 indexing 时能有更多的 Nodes 能分担处理,但一个 Cluster 可能有许多的 Index ,在各种混合分配的情况下,若是 shard allocation 的机制刚好把这个 Index 把 shard 分到同一个 Node 身上的话,这样就达不到我们要的目的。
因此可以透过 index.routing.allocation.total_shards_per_node
的设定,来限制每个 node 可以被分配存放这个 index 多少个 shard,设定方式如下:
PUT /my-index-000001/_settings
{
"index" : {
"routing.allocation.total_shards_per_node" : 5
}
}
当 Cluster 已经因为太多的 shards 导致不太稳定时,我们可以透过以下的方式来进行调整或修正。
底下分别是这些建议的个别说明。
针对 time-based 资料,我们可以提高切 Index 的时间颗粒度,例如本来是 1天 切一个 Index,我们可以改成 1个月、或 1年 来切 Index。
如果是使用 Index Lifecycle Management 来处理 time-based indices 时,就可以透过提高 max_age
, max_docs
, max_size
的这些配置来达到同样的目的。
如果是使用 ILM 的 max_age
机制来进行 Index 的 rollover 时,有可能会产生出空的 index,这些空的 indices 也会占用到一些系统资源,这样的 Index 应该查询出来并且删除。
透过 Segment Files 的 merge 来减少占用的系统资源与空间,将资源能提供给其他的任务。
也因为 forcemerge 的执行时很占用系统资源,所以建议要在系统较不忙的时候来做这个动作。
POST /my-index-000001/_forcemerge
如果 Index 已经不再会写入新的资料时,可以透过 Shink API 来将 primary shard 的数量减少。详细的设定方式可以参考先前的文章,或是 官方文件 - Shrink index API。
若是使用 ILM 的话,也可以在 warm phase 时设置 Shrink 的处理。
例如原先我们是以 日 来当作 time-based indices 的切割单位,若是 index 数量太多,因此造成 shard 数量太多,我们可以透过 reindex 的方式这些 indices 的资料合并到以 月 为单位的 index。
POST /_reindex
{
"source": {
"index": "my-index-2099.10.*"
},
"dest": {
"index": "my-index-2099.10"
}
}
这样也会是一种减少 shard 数量的方式。
查看最新 Elasticsearch 或是 Elastic Stack 教育训练资讯: https://training.onedoggo.com
欢迎追踪我的 FB 粉丝页: 乔叔 - Elastic Stack 技术交流
不论是技术分享的文章、公开线上分享、或是实体课程资讯,都会在粉丝页通知大家哦!
此系列文章已整理成书
乔叔带你上手 Elastic Stack:Elasticsearch 的最佳实践与最佳化技巧
书中包含许多的修正、补充,也依照 Elastic 新版本的异动做出不少修改。
有兴趣的读者欢迎支持! 天珑书局连结
tags: OC 30 day 因为工作的需求,今天跳级来写写网路请求。 NSURLConnecti...
DNS Message DNS 的讯息传递也是两种:Query 与 Reply(就是要求与回覆),它...
在决定铁人赛的题目前,我刚好有个前同事传讯息问我近况,顺便想套一下我当时的薪水,当时在公司大家对於薪...
=x= 🌵 CONTACT Page 寄信页的「我不是机器人」验证功能,後端实作。 Google r...
今天开箱第四颗宝石,我们将比较 RDS 与 EC2 方案的不同处,用来切入为何 AWS RDS 成...