当前位置: 首页 > news >正文

如何减少 Elasticsearch 集群中的分片数量

作者:来自 Elastic Alex Salgado

在本综合指南中了解 Elasticsearch 分片如何影响集群性能,包括如何获取分片数量、更改默认值以及在需要时减少分片数量。

更多阅读:Elasticsearch 中的一些重要概念: cluster, node, index, document, shards 及 replica

刚接触 Elasticsearch?参加我们的 Elasticsearch 入门网络研讨会吧。你也可以立即开始免费的云试用,或在本地尝试 Elastic。


Elasticsearch 减少分片数量 —— 说明与代码示例

当集群(cluster)中分片(shards)过多时,可以采取一些步骤来减少分片数量。本指南介绍了删除或关闭索引(indices)以及重新索引到更大索引的方法。下面我们将说明如何减少新建索引的分片数量、如何减少已存在索引的分片数量、如何减少主分片数量,以及如何减少基于时间的索引的分片数量。

如何减少新建索引的分片数量

在创建新索引时,应确保新建分片数量配置为尽可能小。

以常见的日志存储场景为例。自 Elasticsearch 7.0 起,默认每个索引有 1 个主分片,这已经是一个显著改进。然而,即使在这种更保守的配置下,你仍可以根据实际数据量进行优化。一个分片通常可以在保持良好性能的情况下容纳 10 到 50GB 的数据,因此如果你生成的数据量低于这个范围,可以保持默认的 1 个分片。对于更大的数据量,可以遵循每 10–30GB 一个分片的一般原则,并根据搜索与索引性能需求进行调整。

最简单的方式是创建一个索引模板并将其存储在集群状态中。以下请求将创建一个名为 “template_1” 的索引模板。它会应用到所有以 “log” 开头的新建索引名称上,并将每个索引的主分片数量设置为 1。

PUT _index_template/template_1
{"index_patterns": ["log*"],"template": {"settings": {"index.number_of_shards": 1,"index.number_of_replicas": 1  // Default is 1 if not specified}}
}

注意:如果你没有在模板中指定 number_of_replicas,Elasticsearch 将使用默认值——每个主分片 1 个副本。你可以根据容错和性能需求进行调整。

具体代码语法可能会因所使用的 Elasticsearch 版本而有所不同,请参考创建索引模板的文档。

如何减少现有索引的分片数量

减少副本分片数量

减少分片数量的一个简单方法是降低副本数量。更改副本数量可以通过单个请求动态完成,只需几秒钟。

通常建议每个索引有 1 个副本分片,即每个分片在另一个节点上保留一份副本(除非你有大量并行搜索请求)。副本用于故障切换保护和提升搜索性能。如果包含主分片的节点宕机,其中一个副本会被提升为主分片,确保数据在搜索和新索引操作中保持可用。副本还能提高集群的弹性,并更均匀地分配负载。

不过,副本策略取决于集群的瓶颈。如果集群因大量索引操作而过载,将副本数量减少为 0 可以快速缓解压力。反之,如果集群在搜索性能上有瓶颈且容量充足,增加副本反而能帮助分担搜索负载。需要注意的是,将副本数设为 0 会失去容错能力,不应长期保持这种设置。

记住,副本数量也可以在前面展示的索引模板中进行配置。

以下请求会将所有以 “log” 开头的索引的副本分片数量设置为 0:

PUT log*/_settings
{"index" : {"number_of_replicas" : 0}
}

减少主分片数量

每个索引的主分片数量无法动态更改 —— 它是不可变的。用于在多个分片之间分配新文档的路由算法依赖于主分片总数。因此,减少现有索引的主分片数量会稍微复杂一些。

基本上,你需要创建一个新索引并复制所有数据。可以使用两种 API 来实现:Shrink APIReindex API。这两种 API 各有优缺点,适用性取决于你的配置和需求。Shrink API 速度更快,但只能用于只读索引(即不再更新或插入文档的索引);Reindex API 则可用于活动索引。

使用 Shrink API 减少分片数量

你可以根据索引大小将分片过多的索引缩减为更少的分片数量 —— 请参考相关的大小调整文档以获取指导。可缩减到的分片数量有一定限制,请务必阅读文档以确认此选项是否适合你的情况。

请注意,缩减索引需要一定的维护时间。首先,索引的所有主分片必须分配到同一节点上。请确保该节点有足够的存储空间(如果没有,请考虑使用下文所示的 Reindex API)。然后,需要将索引标记为只读。

以下请求将把所有以 “log” 开头的索引设置为只读,并将所有分片移动到名为 “shrink_node_name” 的节点上。

警告: 不要在正在写入的索引上运行此命令。将索引设置为只读会立即阻止所有写入操作,导致索引失败。此方法仅适用于不再接收新数据的索引。

PUT log*/_settings
{"settings": {"index.blocks.write": true,"index.routing.allocation.require._name": "shrink_node_name" }
}

你需要使用下面的命令逐个缩减索引。分片分配会恢复为默认状态,索引也将重新变为可写。

POST log-1/_shrink/log-shrink-1
{"settings": {"index.routing.allocation.require._name": null,"index.blocks.write": null}
}

具体语法可能会因所使用的 Elasticsearch 版本而有所不同,请参考 Shrink index API 文档。

使用 Reindex API 减少分片数量

如果要缩减的索引仍在被写入,可以使用 Reindex API

Reindex API 可用于将文档分批从一个索引复制到另一个索引。在这种情况下,所有需要在索引时执行的工作都必须重新执行。这使得使用 Reindex API 比直接复制整个分片更慢,但仍是相对较快的过程。

Reindex API 会创建源索引的一个时间点视图,并将其保存在临时搜索上下文中,然后从该上下文中复制所有文档。在重新索引过程中创建的文档不会被复制,因为它们不存在于该上下文中。

有两种方法可以进行操作。第一种方法只需要一次重新索引操作,第二种需要两次。以下是这两种方法的工作方式。

在第一种方法中,你需要在开始重新索引之前,先将所有索引写入流量重定向到新索引。步骤如下:

  1. 创建一个具有更少分片的新索引

  2. 创建一个同时搜索旧索引和新索引的别名

  3. 将所有写入流量重定向到新索引

  4. 启动从旧索引到新索引的重新索引过程

  5. 完成后,删除别名并删除旧索引

这种方法确保数据零丢失,同时避免了双写或多次重新索引的复杂性。

步骤 1: 创建具有所需分片数量的目标索引:

PUT log-shrink-1
{"settings": {"index.number_of_shards": 1,"index.number_of_replicas": 1}
}

步骤 2: 创建一个别名,使其可以同时搜索两个索引:

POST _aliases
{"actions": [{"add": {"index": "log-1","alias": "logs-search"}},{"add": {"index": "log-shrink-1","alias": "logs-search"}}]
}

步骤 3: 将所有写入流量重定向到新索引

注意:在你的应用程序中,将目标索引从 "log-1" 改为 "log-shrink-1" 即可

步骤 4: 将所有文档从旧索引复制到新索引:

POST _reindex
{"source": {"index": "log-1"},"dest": {"index": "log-shrink-1","op_type": "index"}
}

步骤 5: 重新索引完成后,删除别名并删除旧索引:

POST _aliases
{"actions": [{"remove": {"index": "log-1","alias": "logs-search"}}]
}DELETE log-1

第二种方法略有不同,索引写入流量仅在第一次重新索引操作完成后才重定向到新索引,这需要运行第二次重新索引操作,将第一次重新索引期间在旧索引中写入的新文档复制过来。步骤如下:

  1. 创建一个具有更少分片的新索引(同上文步骤 1)

  2. 启动从旧索引到新索引的重新索引过程(同上文步骤 4)。记录开始此步骤的时间戳

  3. 完成后,将所有写入流量重定向到新索引(同上文步骤 3)

  4. 创建一个别名,使其可以同时搜索两个索引(同上文步骤 2)。注意,这允许在下一步重新索引期间,新索引到旧索引的文档仍可被搜索,但有些文档可能暂时在搜索结果中出现两次

  5. 运行第二次重新索引操作,将新索引的文档复制过来,使用下面的命令并使用步骤 2 中记录的时间戳:

    POST _reindex
    {"source": {"index": "log-1","query": {"range": {"@timestamp": {"gte": "2025-01-28T10:00:00"}}}},"dest": {"index": "log-shrink-1","op_type": "index"}
    }
  6. 当第二次重新索引操作完成后,你可以删除旧索引和别名(同上文步骤 5)。

为基于时间的索引减少分片数量

如果你使用基于时间的索引名称,例如每日日志索引,但数据量不足,减少分片的一个好方法是改用每周或每月的索引模式。

你也可以按月、季度或年份将旧的只读索引进行分组。最简单的方法是使用 Reindex API。

为多租户索引减少分片数量

当你有多租户场景,每个客户一个索引时,减少分片看起来会更困难。

在多租户情况下,你可能有一些大客户,每个索引有一个或多个分片,大小看起来合适。同时,也会有许多客户的索引较小。

如果在这种配置下仍需要为每个客户保留一个索引,可以使用 Filtered Aliases

使用 Filtered Aliases 减少分片数量

Filtered Aliases 不像 “普通” 索引别名那样常见,但它允许你为一个索引创建多个视图。

你可以不为每个租户或客户创建一个索引,而是为所有较小的租户创建一个索引,这些租户小到不值得单独索引。然后添加一个关键字或数字字段来区分这些租户(如客户名称或客户 ID)。

创建索引后,只需在该索引上创建一个过滤别名,并将租户名称作为别名即可。

应用程序不会注意到后台使用了过滤别名,它们只需使用别名即可。但你可以在一个索引中存储许多不同租户,避免分片过多。

重要考虑事项:这种方法可能会受 “嘈杂邻居” 影响 —— 当不同租户共享同一分片时,更活跃的租户可能影响较安静租户的性能。监控租户的活动模式,并考虑将使用特性相似的租户分组。

前提是你为所有客户使用兼容的数据模型。

下面的请求展示了如何在索引上创建过滤别名:

POST _aliases
{"actions":[{"add":{"index":"small-customers","alias":"customer-1","filter":{"term":{"customer-id":"1"}}}}]
}

在多租户环境中减少分片数量时,你可以为所有小型租户创建一个新索引,并使用 Reindex API 复制数据。如果需要添加新字段以区分租户,例如 "customer-id",可以使用 ingest pipeline 添加新字段。

不想担心分片吗?如果管理分片数量、容量和优化对你来说太复杂,可以考虑 Elasticsearch Serverless —— 我们的托管产品,你可以专注于业务逻辑,而我们处理所有基础设施复杂性,包括优化的分片管理和自动扩缩容。

了解更多关于分片的信息

  • Elasticsearch shards 和 replicas:实用指南

  • Nodes、Clusters & Shards - Elasticsearch 101 课程,第 2 集

原文:https://www.elastic.co/search-labs/blog/elasticsearch-shards-reduce-change-count

http://www.dtcms.com/a/461225.html

相关文章:

  • 当通过API发送请求的方式自动触发Jenkins job报错HTTP Status 403 – Forbidden的解决办法
  • 一个网站如何工作流程建立网站需要哪些手续
  • H3C网络设备 实验二:搭建两个局域网,使两个局域网相互通信(路由器,固定ip)
  • 临平房产做网站的公司wordpress屏蔽功能org
  • Skywalking 的本地开发配置
  • iOS 上架 App 全流程实战,应用打包、ipa 上传、App Store 审核与工具组合最佳实践
  • JavaScript核心构成与基础语法详解2
  • 邹平网站建设公司淘宝网站开始怎么做
  • fs 文件系统:Node.js 操作磁盘的 “万能工具”
  • Android + iOS 手机抓包 App 实操教程
  • 智慧新零售时代:施易德系统平衡技术与人力,赋能门店运营
  • 标准编码与算法
  • Python获取变量名本身​​——varname库
  • 专业站全返利网站建设
  • 网站设计提案安阳市建设工程领域网站
  • 鸿蒙(OpenHarmony)声明式 UI 开发入门:从「智慧校园」项目学基础语法
  • js移动开发框架
  • 【腾讯拥抱开源】Youtu-Embedding:基于CoDiEmb的一个协作而独特的框架,用于信息检索与语义文本相似性中的统一表征学习
  • 西蔵自治区建设厅网站wordpress防盗链插件
  • VSCode中使用conda activate 虚拟环境,没报错,但没进入环境
  • vue修改element-ui的默认的class
  • ModuleNotFoundError: No module named ‘UI_xiangmu‘
  • 网站建设方案及报价霍州做网站
  • mybatis-generator插件自动生成mapper及其实体模型配置
  • 计算机毕业设计 基于k-means的校园美食推荐系统 Python 大数据毕业设计 Hadoop毕业设计选题【附源码+文档报告+安装调试】
  • 【代码大模型-后门安全】Backdoors in Neural Models of Source Code
  • javaweb后端优雅处理枚举
  • 帝国cms小程序搞起来简直好用的不行
  • 高效批量调整图像尺寸的方案
  • 单片机供电处3.3V大电容导致程序可进调试但是无法暂停到具体语句