4. 分片与副本的高可用工程
分片与副本是 Elasticsearch 高可用的物理基础。主分片决定数据能否写入与水平扩展能力,副本分片决定节点故障时数据是否仍可读、能否快速接管。工程上真正难的不是“把副本数设成 2”,而是让分片在节点间合理分布、大小可控、故障后能有序恢复,并且在网络分区时避免出现两个主节点同时接受写入的脑裂局面。
一、分片分配策略:让分片落在正确的位置
分配由主节点负责决策,核心约束来自分配感知(awareness)、过滤规则(filtering)和磁盘水位。分配感知通过 cluster.routing.allocation.awareness.attributes 指定属性(如 zone、rack),同一分片的主副本会被强制分散到不同属性值;若某属性值节点全部离线,可配合 force.zone.values 允许副本临时落到剩余区域,避免分片无法分配。
过滤规则用于把索引“钉”在特定节点上,例如冷热分层:热节点打 node.attr.tier: hot,冷节点打 tier: cold,索引创建时用 index.routing.allocation.include.tier 指定。磁盘水位是硬约束:低于 low(默认 85%)不再新分配,超过 high(默认 90%)尝试迁走分片,超过 flood_stage(默认 95%)索引转为只读。工程上应把水位与节点磁盘容量一起规划,而不是等告警后再清理。
二、副本数选择:可用性与成本的平衡
副本数 number_of_replicas 决定每个主分片有几份冗余。单节点集群设副本无意义;3 个数据节点、1 副本可容忍 1 个节点故障;若要求容忍 2 个节点同时故障,至少需要 2 副本且节点数不少于 3。副本还承担读吞吐:查询会轮询主副本,副本越多读能力越强,但写入需同步到所有副本,写放大和刷新开销随之上升。
一个常见误区是“副本数等于节点数就安全”。实际上副本分配受感知属性约束,若 3 个节点同处一个机架,机架断电仍会整体不可用。因此副本数必须与故障域一起设计:跨机架、跨可用区部署时,副本数至少覆盖最大可容忍故障域数量。
三、分片大小控制:避免“大分片”与“小分片”两个极端
官方经验是单个分片 10~50GB 较为健康,搜索类场景可更小,日志类可接近上限。分片过大导致恢复慢、单分片查询延迟高、重新分配代价大;分片过小则集群元数据膨胀、每分片固定开销累积。估算公式可简化为:
主分片数 ≈ 索引总数据量 / 目标分片大小
例如:总数据 600GB,目标 30GB/分片 → 主分片数 ≈ 20
分片数在索引创建后不可直接修改(只能 _shrink 或 _split),因此要预留增长空间。对按天滚动的日志索引,可用 ILM 在 rollover 时按大小或文档数触发新索引,把“分片大小控制”变成持续动作而非一次性设置。
四、分片恢复流程:从失联到转绿
当数据节点失联,主节点先将其标记为离线,并把该节点上的主分片对应的副本提升为新的主分片,保证写入不中断。随后触发分片重新分配,把缺失的副本补到其他节点。恢复分两种:peer recovery 从同分片的其他副本复制段文件,速度快;snapshot recovery 从快照仓库恢复,适合跨集群或大分片。恢复期间可通过 _cat/recovery?v 观察 stage(index、translog、finalize)和 bytes_percent。
恢复会占用网络与磁盘 IO,若同时恢复大量分片会拖慢集群。可通过 cluster.routing.allocation.node_concurrent_recoveries(默认 2)和 indices.recovery.max_bytes_per_sec(默认 40MB/s)限流。判断恢复是否健康,看 _cluster/health 的 active_shards_percent 是否回到 100%、unassigned_shards 是否归零,以及 _cat/recovery 中是否还有长时间停留在 translog 阶段的分片。
五、脑裂风险规避
脑裂指网络分区后两侧都认为自己是主节点,各自接受写入,导致数据分叉。Elasticsearch 7.x 以后用基于 quorum 的选举:主节点数 N,法定票数为 N/2 + 1。3 个主节点时 quorum=2,少数派一侧无法选出主节点,只能拒绝写入,从而避免双主。2 个主节点时 quorum 仍为 2,任何一台故障都会失去写入能力,因此生产环境建议至少 3 个专用主节点且为奇数。
配置上要固定 discovery.seed_hosts 与 cluster.initial_master_nodes(仅首次启动),避免节点自行组网;跨机房部署时把主节点集中在同一低延迟区域,数据节点可跨区,但不要跨高延迟链路做选举。若使用云托管服务,应确认其主节点拓扑与故障域隔离策略。
_cat/recovery 与 _cluster/health 验证恢复闭环。| 参数 | 典型值 | 作用与判断 |
|---|---|---|
| number_of_replicas | 1~2 | 决定可容忍节点故障数与读吞吐 |
| 目标分片大小 | 10~50GB | 过大恢复慢,过小元数据膨胀 |
| node_concurrent_recoveries | 2 | 限制并发恢复,保护 IO |
| max_bytes_per_sec | 40MB/s | 恢复带宽上限,按网络调整 |
| 主节点数 / quorum | 3 / 2 | 奇数部署,避免脑裂与写入中断 |
把以上五点串起来,分片与副本的高可用就不是单点配置,而是一套从拓扑、参数到恢复验证的工程闭环:分配策略决定“放哪里”,副本数决定“坏多少还能活”,分片大小决定“恢复多快”,恢复流程决定“故障后多久转绿”,脑裂防护决定“分区时会不会写坏数据”。