4. 分片原理深度解析:主分片与副本分片、分片路由算法、分片分配策略、分片大小与数量权衡

在 Elasticsearch 集群中,分片(Shard)是数据分布与并行计算的核心单元。理解分片的工作原理,是进行索引调优的前提。本章将从分片类型、路由算法、分配策略以及容量权衡四个维度,深入剖析分片机制。

4.1 主分片与副本分片

每个索引在创建时,会被划分为多个主分片(Primary Shard)。每个主分片可以拥有零个或多个副本分片(Replica Shard)。副本分片是主分片的完整拷贝,用于提供高可用性和扩展搜索吞吐量。

特性 主分片(Primary) 副本分片(Replica)
数据写入 所有索引写入操作首先到达主分片 不直接接收写入,通过主分片同步
数据读取 参与搜索,默认轮询副本 参与搜索,分担主分片负载
高可用 主分片故障时,由副本晋升为新的主分片 提供冗余,防止数据丢失
数量变更 索引创建后不可修改 可动态调整
关键原则:副本分片数建议至少为 1(生产环境建议 1~2)。副本数过多会占用大量磁盘和内存资源,但能显著提升搜索并发能力。
主分片与副本分片关系 主分片 P0 主分片 P1 主分片 P2 副本 R0 副本 R1 副本 R2 同步机制 写入 → 主分片 主分片同步 → 副本 副本确认 → 返回成功

4.2 分片路由算法

当客户端写入或查询一个文档时,Elasticsearch 需要确定该文档应落在哪个主分片上。这一过程由路由算法完成。

默认路由公式为:

shard = hash(_routing) % number_of_primary_shards

其中 _routing 默认使用文档的 _id 字段。用户也可以显式指定路由值,实现路由感知(Routing Awareness)。

路由优化技巧:
  • 自定义路由:将同一用户的文档路由到同一分片,可大幅提升批量查询性能。
  • 路由分区(Routing Partition):配合 routing_partition_size 参数,避免单个分片过热。
  • 注意:使用自定义路由后,不带路由的查询会广播到所有分片,增加集群压力。
分片路由算法流程 文档 _id / _routing hash() 计算 % 主分片数 分片编号 路由示例 文档 _id = "user_123" hash("user_123") % 5 = 3 → 分片 P3

4.3 分片分配策略

分片分配是指将主分片和副本分片放置到集群中各个节点上的过程。Elasticsearch 提供了多种分配策略,以适应不同的部署场景。

4.3.1 基于磁盘的分配

默认策略。节点会根据磁盘使用率决定是否接收新分片。当节点磁盘使用率超过 cluster.routing.allocation.disk.watermark.low(默认 85%)时,不再分配新分片;超过 high(默认 90%)时,会将部分分片迁移到其他节点。

4.3.2 基于分片总数的分配

通过 total_shards_per_node 限制每个节点上某个索引的分片数量,防止单个节点承载过多分片。

4.3.3 基于可用区的分配

在 Kubernetes 多可用区部署中,使用 cluster.routing.allocation.awareness.attributes 确保主分片和副本分片分布在不同的可用区,实现跨 AZ 高可用。

分配策略 配置参数 适用场景
磁盘水位线 disk.watermark.low/high 通用场景,防止磁盘写满
分片总数限制 total_shards_per_node 控制节点负载,避免热点
可用区感知 awareness.attributes 多可用区 Kubernetes 集群
过滤分配 index.routing.allocation.include/exclude 节点维护、硬件隔离
Kubernetes 环境注意:当 Pod 被调度到新节点时,Elasticsearch 会自动触发分片重平衡。建议配合 cluster.routing.rebalance.enable 参数控制重平衡时机,避免频繁迁移影响性能。

4.4 分片大小与数量权衡

分片大小和数量是索引调优中最关键的决策之一。设置不当会导致性能瓶颈或资源浪费。

4.4.1 分片大小建议

  • 推荐范围:每个分片 10GB ~ 50GB。
  • 上限:单个分片不宜超过 100GB,否则段合并和恢复时间会显著增加。
  • 下限:分片过小(< 1GB)会导致分片数量过多,增加集群管理开销。

4.4.2 分片数量计算

分片数量 = 数据总量 / 目标分片大小。同时需要考虑节点数量和副本数:

总数据量 = 1000GB
目标分片大小 = 40GB
主分片数 = 1000 / 40 = 25
副本数 = 1
总分片数 = 25 * (1 + 1) = 50

4.4.3 权衡矩阵

因素 分片过多 分片过少
搜索性能 并行度高,但协调开销大 并行度低,单分片压力大
索引写入 频繁刷盘,I/O 压力大 写入吞吐受限
集群管理 分片重平衡慢,内存占用高 迁移快,但扩展性差
故障恢复 恢复时间长,网络开销大 恢复快,但数据丢失风险高
Kubernetes 集群建议:每个节点上的分片数建议控制在 节点 CPU 核心数 * 2 以内。例如 8 核节点,最多承载 16 个分片。同时利用 elasticsearch.alpha.kubernetes.io/coordination 注解优化分片分配。

通过深入理解分片原理,你可以在 Kubernetes 集群中更精准地规划索引结构,为后续的副本调优和性能优化打下坚实基础。