写点什么

大数据 -191 Elasticsearch 集群规划与调优:节点角色、分片副本、写入与搜索优化清单

作者:武子康
  • 2025-12-22
    山东
  • 本文字数:4967 字

    阅读完需:约 16 分钟

大数据-191 Elasticsearch 集群规划与调优:节点角色、分片副本、写入与搜索优化清单

TL;DR

  • 场景:从 2–4 节点业务搜索到 ELK/OLAP 大集群,做角色划分、容量推算与性能调优

  • 结论:先定角色与容量边界,再定分片/副本与写入策略,最后用搜索侧与运维侧指标闭环

  • 产出:一套可复用的集群规划模板 + 分片副本规则 + 写入/搜索调优抓手 + 常见故障速查


版本矩阵


Elasticsearch 集群模式

Elasticsearch 是一个分布式搜索引擎,集群模式是指由多个节点(node)组成的一个集群(cluster),它们协同工作以提供更高的性能、扩展性和容错性。每个集群都有唯一的名称,所有属于同一集群的节点使用相同的集群名称相互识别。


在集群架构中,节点根据其功能职责被划分为三种主要类型,每种类型在集群中承担着不同的角色:


  1. 主节点(Master Node)

  2. 核心职责

  3. 管理集群级别的元数据操作,包括索引创建/删除、分片分配等

  4. 监控集群状态,跟踪节点的加入或离开

  5. 处理集群范围内的配置变更

  6. 特性

  7. 通常不参与实际的数据搜索和存储操作

  8. 为保证高可用性,建议配置 3 个主节点(奇数个)组成主节点集群

  9. 示例:当新建索引时,客户端请求首先由主节点处理,主节点决定新索引的分片分配方案

  10. 数据节点(Data Node)

  11. 核心功能

  12. 存储索引数据的实际分片

  13. 处理与数据相关的 CRUD 操作(创建、读取、更新、删除)

  14. 执行搜索和聚合等计算密集型任务

  15. 重要特性

  16. 存储数据的多个副本,确保数据高可用性

  17. 需要较强的 CPU、内存和存储资源

  18. 应用场景:电商网站的搜索服务通常需要部署多个数据节点来处理大量商品数据的存储和检索

  19. 协调节点(Coordinating Node)

  20. 工作流程

  21. 接收客户端请求

  22. 将请求路由到相关数据节点

  23. 收集各节点的响应

  24. 合并结果返回给客户端

  25. 特点

  26. 不存储数据,也不参与主节点选举

  27. 默认情况下所有节点都具备协调功能

  28. 专用协调节点通常用于大型集群,减轻其他节点的请求处理负担

  29. 示例:在分布式日志分析系统中,协调节点负责将搜索查询分发到存储日志的数据节点


在实际部署中,一个节点可以同时承担多种角色(如既是数据节点又是协调节点),但生产环境通常建议将主节点与数据节点分离,以确保集群稳定性。节点类型的合理配置对集群性能、可靠性和资源利用率有重大影响。

集群规划

规划的重要性

在部署 Elasticsearch 集群时,规划是至关重要的基础步骤,直接影响集群的性能表现、未来扩展能力以及日常运维的便捷性。合理的规划可以避免后期频繁的架构调整,确保集群能够稳定高效地运行。

核心规划要素

1. 主节点规划

主节点是集群的大脑,负责维护集群状态、索引元数据和执行分片分配等重要操作。规划时需特别注意:


  • 数量配置:建议至少配置三个专用主节点(master-only nodes)以形成法定人数(quorum),确保集群高可用性。当其中一个节点故障时,剩余两个节点仍能正常选举新的主节点。

  • 资源分配:由于主节点不处理数据存储和搜索请求,可以配置相对较小的资源(如 2-4 核 CPU,4-8GB 内存)。

  • 部署位置:应将主节点分散在不同机架或可用区(AZ)以防范单点故障。例如在 AWS 环境中,可以将三个主节点分别部署在 us-east-1a、us-east-1b 和 us-east-1c 三个可用区。

2. 数据节点规划

数据节点是集群的主力,负责存储索引数据、执行搜索和分析操作。规划要点包括:


  • 资源需求

  • 内存:建议每个节点配置 32GB 以上内存,其中一半(16GB)分配给 JVM 堆,剩余用于文件系统缓存。

  • 存储:根据数据量和增长预期确定,建议使用 SSD 存储以获得更好的 IO 性能。例如,预计年增长 10TB 数据的业务,可按 3 节点×2TB SSD 配置。

  • 分片策略:每个节点建议承载不超过 20-25 个分片,每个分片大小控制在 30-50GB 之间。例如 10TB 数据可分为 200 个 50GB 的分片,需要 8-10 个数据节点。

  • 扩展性:采用水平扩展策略,初期可按最小需求配置,后续随数据增长逐步添加节点。例如电商平台在促销季前可临时增加数据节点应对流量高峰。

3. 协调节点规划

协调节点作为请求的入口和调度中心,在大规模集群中特别重要:


  • 功能分离:将搜索请求的聚合、排序等计算密集型操作从数据节点卸载到协调节点,减轻数据节点负担。

  • 资源配置:需要较强的 CPU 资源(8-16 核)处理请求路由和结果聚合,内存需求中等(16-32GB)。

  • 部署场景:特别适用于搜索请求量大(如每天百万级查询)或复杂聚合查询多的场景。例如新闻网站可部署 3-5 个协调节点处理用户搜索请求。

  • 负载均衡:配合负载均衡器(如 Nginx、HAProxy)使用,实现请求的均匀分发和故障转移。

规划考虑

我们在业务上需要考虑的是:


  • 当前的数据量有多大?数据增长情况如何?

  • 你的机器配置如何?CPU?内存?硬盘容量?

推算依据

  • Elasticsearch JVM Heap 最大可以设置 32G

  • 30G heap 大概能处理的数据量 10T

  • 内存很大的话,比如 128G 的内存,可以考虑一台机器上部署多个 Elasticsearch

应用场景

  • 用于构建业务搜索功能模块,且多是垂直领域的搜索。数据量级几千万到数十亿级别,一般 2-4 台机器的规模

  • 用于大规模的实时 OLAP(联机处理分析),经典的如 ELK Stack,数据规模可以达到千亿或更多,几十到上百节点的规模

角色分配

节点角色:


  • MasterNode: node.master 设置为 true,节点可以作为主节点

  • DataNode:node.data 设置为 true,默认是数据节点

  • CoordinateNode:协调节点,一个节点只作为接收请求、转发请求到其他的节点、汇总各个节点返回数据等功能的节点,就叫协调节点。(如果仅担任协调节点,需要将 MasterNode 和 DataNode 设置为 false,一个节点可以充当一个角色,也可以充当多个角色)


节点角色如何分配:


  • 小规模集群,不需要严格区分

  • 中大规模集群(十个节点以上),应考虑单独的角色充当。特别并发查询量大,查询的合并量大,可以增加独立的协调节点。角色分开的好处是分工分开,互不影响。如不会因协调角色负载过高而影响数据节点的能力。

设置分片

  • 说明:分片数指定后不可变,除非索引重建。

  • 分片设置的可参考原则:Elasticsearch 推荐的 JVM 最大的堆空间是:30-32G,所以把分片的最大容量限制在 30G,然后对分片数量做合理估算。在开始阶段,一个好的方案是根据节点的数量按照 1.5-3 倍的原则来创建分片。例如:如果你有三个节点,则推荐你创建的分片数量不超过 9 个(3*3)个。当性能开始下降时,增加节点,ES 会平衡分片的放置。对于基于日期的索引需求,并且对索引数据的搜索场景非常少,也许这些索引量会成百上千,但是每个索引的大小缺只有 1GB 甚至更小。对于这种场景,建议只需要为索引分配 1 个分片。对于日志管理的需求,就是类似于日期索引需求,日期索引会很多,但是每个索引存放的数据量缺很少。

设置副本

分片应该设置几个副本呢?


  • 为了保证高可用,副本数设置为 2 即可。但是要求集群至少有 3 个节点,来分开存放主分片、副本。

  • 如果并发量大时,查询性能下降,则增加副本数,提高并发查询的能力。

  • 注意:新增副本时主节点会自动协调,然后拷贝数据到新增的副本节点,副本数是随时都可以调整的。


PUT /wzk_temp_index/_settings{  "number_of_replicas": 1}
复制代码

集群调优

Index 调优

在业务场景中,很多时候数据都是从 MySQL 集群,再抽取到 ES 的 Index 中。如果你的场景的数据是不断变化的,那就要求 ES 中的数据也要有一个快速变化的要求,这样才可以保证 MySQL 和 Elasticsearch 中的数据保持一致。

副本数 0

如果集群是首次写入数据,那么可以先设置为 0,后续写完再根据业务要求设置为 2(比如高可用),节约集群生成索引的过程。


PUT /wzk_temp_index/_settings{  "number_of_replicas": 0}
复制代码

自动生成 ID

自动生成 DocID,通过 Elasticsearch 写入流程可以看出,如果写入 Doc 时外部指定了 id,那么 Elasticsearch 会先尝试读取原来的 Doc 的版本号,以判断是否需要更新数据,这个操作涉及到了磁盘,如果是自动生成 DocID 则可以避免这个问题。

mappings

合理设置 mappings:


  • 将不需要建立索引的字段 index 属性设置为 not_analyzed 或 no。对字段不分词,或者不索引,可以减少很多 CPU 的计算。尤其是 Binary 类型,默认情况下 CPU 会很高,而且这种分词通过没有任何意义。

  • 减少字段的内容长度,如果原始数据的大段内容不用全部建立索引,则可以尽量减少不必要的内容

  • 使用不同的分析器(analyzer),不同的分词器在建立索引的过程中,运算的复杂度也有较大的差异。

source 字段

调整 _source 字段,source 字段用于存储原数的 doc 数据,对于部分不需要存储的数据,可以通过 index excludes 过滤,或者将 source 禁用,一般用于索引和数据分离,这样可以降低 I/O 的压力,不过业务场景中大多数都不会禁用 Source。

analyzed 禁用 norms

norms 用于在搜索中计算 doc 的评分,如果不需要评分,则可以将其禁用。


"title": {  "type": "string",  "norms": {    "enabled": false  }}
复制代码

刷新间隔

调整索引的刷新间隔,该参数缺省是 1 秒,强制 ES 每秒创建一个新的 Segment,从而保证新写入的数据近实时可见,可以被搜索到。比如该参数被调整为 30 秒,降低了刷新的次数,把刷新操作消耗的资源给释放出来给 index 操作使用。


PUT /wzk_temp_index/_settings{  "index" : {    "refresh_interval": "30s"  }}
复制代码


这种方式是牺牲可见性的方式,提高了 index 操作的性能。

批处理

批处理把多个 index 操作请求合并到一个 batch 中去处理,和 MySQL 的 JDBC 的 Batch 有类似之处。如下图所示:



比如每批 10000 个 Document 是一个性能比较好的大小,每批中多少 Document 条数合适,受到很多因素影响而不同。

Search 调优

在存储的 Document 超过 10 亿条后,需要进行搜索调优。

数组分组

ES 用来存储日志,日志的索引管理方式一般都是基于日期,基于天、周、月、年建立索引,如下图,基于天建立索引:



当搜索丹单天的数据,只要要查询一个索引的 Shards 就可以。当需要查询多天的数据时,需要查询多个索引的 Shards。这种方案其实和数据库分表、分库、分区查询方案相比思路是类似的,小数据范围检索而不是大海捞针。

Filter

使用 Filter 替代 Query 在搜索的过程中使用 Query,需要对 Document 的相关度进行打分,使用 Filter 的话,就不会有过滤了,做的事情更少,而且 Filter 理论上更快一些。如果搜索不需要打分,可以直接使用 Filter 查询,如果部分搜索需要打分,建议使用 Bool 查询,这种方式可以把打分和不打分的放到一起:


GET /_search{  "query": {    "bool": {      "must": {        "term": {          "user": "kimchy"        }      },      "filter": {        "term": {          "tag": "tech"        }      }    }  }}
复制代码

ID 字段

将 ID 字段定义为 Keyword 类型是一种常见的优化实践。这种定义方式特别适用于以下场景:


  1. 使用场景分析:


  • 当 ID 主要用作精确匹配查询(如 terms 查询)时

  • 当 ID 不会被用于范围查询(range query)或数值计算时

  • 典型应用场景包括:用户 ID、订单编号、产品 SKU 等标识性字段


  1. 性能优化原理:


  • Keyword 类型在 Elasticsearch 内部会被优化为倒排索引结构,特别适合精确匹配查询

  • 相比数值类型(如 Integer),Keyword 类型避免了为范围查询优化的开销

  • 在 terms 查询场景下,Keyword 类型的查询效率比数值类型更高


  1. 实际案例数据:


  • 某电商平台将商品 ID 从 Integer 改为 Keyword 类型后:

  • 查询响应时间从平均 120ms 降低到 85ms

  • 系统吞吐量提升了约 30%

  • 索引大小减少了 15%(因为不需要存储数值类型的额外元数据)


  1. 实现建议:


{  "mappings": {    "properties": {      "id": {        "type": "keyword"      }    }  }}
复制代码


  1. 注意事项:


  • 该优化主要适用于字符串形式的 ID 或不需要数值运算的数字 ID

  • 如果确实需要范围查询功能,建议保留数值类型

  • 对于既有精确匹配又有范围查询需求的字段,可以考虑使用 multi-fields 特性同时定义两种类型

错误速查

其他系列

🚀 AI 篇持续更新中(长期更新)

AI 炼丹日志-29 - 字节跳动 DeerFlow 深度研究框斜体样式架 私有部署 测试上手 架构研究,持续打造实用 AI 工具指南!AI 研究-132 Java 生态前沿 2025:Spring、Quarkus、GraalVM、CRaC 与云原生落地🔗 AI模块直达链接

💻 Java 篇持续更新中(长期更新)

Java-207 RabbitMQ Direct 交换器路由:RoutingKey 精确匹配、队列多绑定与日志分流实战 MyBatis 已完结,Spring 已完结,Nginx 已完结,Tomcat 已完结,分布式服务已完结,Dubbo 已完结,MySQL 已完结,MongoDB 已完结,Neo4j 已完结,FastDFS 已完结,OSS 已完结,GuavaCache 已完结,EVCache 已完结,RabbitMQ 正在更新... 深入浅出助你打牢基础!🔗 Java模块直达链接

📊 大数据板块已完成多项干货更新(300 篇):

包括 Hadoop、Hive、Kafka、Flink、ClickHouse、Elasticsearch 等二十余项核心组件,覆盖离线+实时数仓全栈!大数据-278 Spark MLib - 基础介绍 机器学习算法 梯度提升树 GBDT 案例 详解🔗 大数据模块直达链接

发布于: 刚刚阅读数: 2
用户头像

武子康

关注

永远好奇 无限进步 2019-04-14 加入

Hi, I'm Zikang,好奇心驱动的探索者 | INTJ / INFJ 我热爱探索一切值得深究的事物。对技术、成长、效率、认知、人生有着持续的好奇心和行动力。 坚信「飞轮效应」,相信每一次微小的积累,终将带来深远的改变。

评论

发布
暂无评论
大数据-191 Elasticsearch 集群规划与调优:节点角色、分片副本、写入与搜索优化清单_大数据_武子康_InfoQ写作社区