Elasticsearch 使用误区之三——分片设置不合理

2024-07-29 11:00:22 浏览数 (1)

1、什么是分片?

在 Elasticsearch 中,每个索引都被划分为多个分片,每个分片可以在多个节点上复制,以确保数据的可用性和冗余。

上图是我本地单节点8.X 集群的 Head 插件截图,绿色代表已分配分片,灰色代表未分配副本分片(单节点所以无法分配副本分片)。

然而,尽管分片允许通过分散数据来扩展,不当的分片可能导致性能瓶颈或稳定性问题。

2、为什么分片策略很重要?

有效的分片关键在于找到正确的平衡。

过多的分片会导致“过度分片”,在这种情况下,管理众多分片的开销超过了其带来的好处,导致查询处理效率降低,可能还会引发集群不稳定。

3、创建分片策略

为了防止这些问题,至关重要的是要根据我们的特定需求开发一个分片策略,这包括:

  • 了解集群的数据和查询:分析咱们所在集群的数据性质和将执行的查询。
  • 基准测试:在类似生产环境中测试不同的分片配置,看看更改如何影响性能。

举例,如下基准测试仅供参考。

分片配置

查询响应时间 (ms)

CPU 使用率 (%)

内存使用率 (%)

搜索吞吐量 (查询/秒)

稳定性评价

5 分片

120

70

65

200

10 分片

95

60

70

230

20 分片

85

75

80

250

50 分片

78

85

90

260

非常低

在实际应用中,应根据具体需求和资源条件,选择最适合的分片配置。

  • 监控:使用 Kibana 等工具监控不同分片大小和配置对集群性能和稳定性的影响。

不幸的是,没有一种万能的分片策略。一种在某个环境中有效的策略可能不适用于其他环境。一个好的分片策略必须考虑到我们的硬件基础设施、业务场景和性能预期。

所以,大厂的意见、建议、经验贴不见得适用我们下厂。这很关键!

4、分片大小的关键考虑因素

4.1 搜索线程

每个分片在单独的线程中处理搜索查询。如果存在太多分片,可能会超负荷节点的搜索线程池,从而减慢查询处理速度。

代码语言:javascript复制
GET /_cat/thread_pool?v&h=id,name,active,rejected,completed

上述命令会显示集群中所有节点的所有线程池的信息,帮助我们识别哪些线程池可能过载。

4.2 分片开销

每个分片无论大小都会增加 CPU 和内存使用的开销。少量大分片通常比许多小分片使用资源更高效。

注意:在 Elasticsearch 中,可以使用一些命令行操作来查看分片的资源使用情况,尤其是关于 CPU 和内存的开销。

虽然没有直接的命令行工具可以显示每个分片的 CPU 使用情况(因为 CPU 使用通常被监控在节点级别而非分片级别),但咱们可以获取关于每个分片内存和存储使用的信息。

API 名称

描述

示例请求

_cat/shards

显示集群中所有分片的信息,包括健康状况、存储使用等。

GET /_cat/shards?v

_cat/allocation

显示集群中每个节点的磁盘分配情况,包括已用和可用空间。

GET /_cat/allocation?v

_nodes/stats

提供节点级的统计信息,包括内存使用情况、CPU使用情况等。

GET /_nodes/stats/jvm?pretty

_cat/segments

提供索引的段信息,帮助了解分片的内部结构,包括段在内存中的大小等。

GET /_cat/segments/my_index?v

4.3 数据段

随着分片内数据的增长,数据会被划分为多个段。

Elasticsearch 在 JVM 堆内存中保留段元数据,以便可以快速检索用于搜索。随着分片的增长,其段被合并成更少的更大的段。这减少了段的数量,意味着在堆内存中保留的元数据更少。

这些段会定期合并,以优化查询性能和资源使用。

源码剖析:Elasticsearch 段合并调度及优化手段

从源码角度剖析 Elasticserach 段合并调优策略

5、分片大小的最佳实践

5.1 理想的分片大小

官方建议:分片大小在 10GB 到 50GB 之间通常是有效的,这有助于平衡资源使用和恢复时间。

Elasticsearch究竟要设置多少分片数?

5.2 节点上的分片数

参考依据之一:根据节点的内存容量保持分片数。例如,具有 30GB 堆内存的节点最多应承载 600 个分片。

参考依据之二:数据节点个数,设置索引分片数据建议数据节点的1(或者1.5)-3倍。

5.3 最佳实践和工具的使用

节点的堆内存:通过以下命令检查每个节点的当前堆内存大小。

代码语言:javascript复制
GET _cat/nodes?v=true&h=heap.current

检查节点上的分片数:使用以下命令来查看每个节点上的分片数量。

代码语言:javascript复制
GET _cat/shards?v=true

显式映射:与其让 Elasticsearch 自动创建映射,不如明确地定义它们,以避免不必要的资源使用。

更多参见《一本书讲透 Elasticsearch》P409-P411Elasticsearch 数据建模章节。

6、使用数据流和 ILM

对于时间序列数据,使用数据流(data stream)和索引生命周期管理 (ILM) 可以简化时间基础索引的管理。

ILM 帮助根据特定标准自动管理滚动和删除,确保有效的数据存储和分片管理。

7、实践中调整分片

  • 滚动标准

设置基于分片大小或文档数量的滚动条件,防止任何单个分片变得过大。

代码语言:javascript复制
PUT my-index-000001/_settings
{
  "index" : {
    "routing.allocation.total_shards_per_node" : 5
  }
}

避免热点:均匀地在节点之间分配分片,以防止任何单个节点成为性能瓶颈。显式映射:与其让 Elasticsearch 自动创建映射,不如明确地定义它们,以避免不必要的资源使用。

8、减少分片数量

如果我们的集群已经存在过度分片问题,可以考虑:

(1)合并索引:将小型、相似的索引合并成更大的索引。

代码语言:javascript复制
POST _reindex
{
  "source": {
    "index": "my-index-2099.10.*"
  },
  "dest": {
    "index": "my-index-2099.10"
  }
}

删除不使用的索引:删除不再需要的索引以释放资源。

代码语言:javascript复制
DELETE my-index-000001

没到这个地方,咱们都多强调一句——删除索引,而不是文档!

删除的文档不会立即从 Elasticsearch 的文件系统中移除。相反,Elasticsearch 会在每个相关分片上标记该文档为已删除。标记的文档将继续使用资源,直到在定期的段合并期间被移除。

(2)压缩索引:减少不再写入数据的旧索引中的分片数量。

9、处理分片相关错误

注意节点最大分片数设置。如果某个操作超过了这个限制,可能需要临时调整该设置或考虑更永久的解决方案,

如增加节点或合并分片。

必知必会两个核心参数:

代码语言:javascript复制
- cluster.max_shards_per_node

- index.routing.allocation.total_shards_per_node

9.1 cluster.max_shards_per_node

这是一个集群级别的设置,用来限制每个节点可以持有的最大分片数。默认值:1000。

其目的是防止单个节点由于持有过多分片而过载,这可能会导致性能下降和稳定性问题。

https://www.elastic.co/guide/en/elasticsearch/reference/8.14/misc-cluster-settings.html

  • 使用场景

防止节点过载——在大规模部署中,防止任何单个节点因分片数量过多而成为性能瓶颈。

集群扩展——在节点添加到集群或从集群中移除时,该设置帮助平衡分片分布,保持集群的健康和性能。

  • 注意事项

(1)如果 cluster.max_shards_per_node 设置得太低,可能会妨碍Elasticsearch正常的分片分配,特别是在集群扩展或收缩时。

(2)可以动态更新这个设置,以适应集群的变化,如节点增加或减少。

代码语言:javascript复制
PUT _cluster/settings
{
  "persistent" : {
    "cluster.max_shards_per_node": 1200
  }
}

9.2. index.routing.allocation.total_shards_per_node

这是一个索引级别的设置,用于限制特定索引的分片可以分配到每个节点的最大数目。这个设置允许对单个索引的分片分布进行更细致的控制。

  • 使用场景

分片均衡——确保一个高流量的索引不会在少数节点上聚集过多分片,从而避免这些节点成为热点。特定索引的性能优化:针对访问模式和查询负载对特定索引进行优化。

  • 注意事项
    • 在索引的生命周期中,我们可能需要根据使用模式和节点的变化调整这个设置。
    • 使用这个设置可以增加配置的复杂性,需要详细监控和调整以确保最佳性能。
    • 虽然这两个设置都涉及分片分配,但 cluster.max_shards_per_node 提供了一个全局的安全网,防止任何节点因分片过多而过载。
    • 而 index.routing.allocation.total_shards_per_node 允许对单个索引进行更细粒度的控制。在实践中,这两个设置可以同时使用,以确保节点不会因全局或局部的分片分布不均而影响整体的Elasticsearch集群性能。

总的来说,适当配置这两个参数能够有效地管理和优化 Elasticsearch 集群的分片分布,从而提高查询性能和系统稳定性。在实际操作中,应根据集群的具体业务场景需求和表现来调整这些设置,以达到最佳的运行效果。

10、结论

在 Elasticsearch 中,有效地管理分片对于维护最佳性能至关重要。通过仔细规划我们的分片策略并定期监控分片性能和资源使用情况,可以确保 Elasticsearch 集群保持稳定、可扩展和快速。

记住,最好的分片方法是能够适应我们的数据和查询需求的不断变化的方法。

0 人点赞