基于本文回答
0
评论

Elasticsearch 中的Shard(分片)和 Replica(副本)

知识点图片

在 Elasticsearch (ES) 中,Shard(分片)Replica(副本) 是其分布式架构的核心概念。理解它们对于设计高性能、高可用的搜索集群至关重要。

简单来说:

  • Shard (分片):是为了水平扩展(能存更多数据,能并行处理)。
  • Replica (副本):是为了高可用(数据不丢)和提升读取性能(并发查询)。

1. Shard(分片 / 主分片)

在 ES 中,一个 Index(索引) 可能包含海量的数据,这些数据可能超过了单个节点的硬件限制(如硬盘容量、处理能力)。为了解决这个问题,ES 将索引划分为多个部分,每一部分就叫做一个 Shard

通常我们说的 Shard 指的是 Primary Shard(主分片)

  • 本质:每一个 Shard 本质上都是一个独立的、功能完整的 Lucene 索引
  • 作用
    • 水平扩展:允许将一个大索引的数据分布在集群的不同节点上。
    • 并行处理:查询时,ES 可以同时在多个分片上并行搜索,从而提高性能。
  • 关键特性
    • 数量固定:在创建索引时,主分片的数量一旦指定,通常不能修改(除非使用 Reindex 重建索引,或者使用 Split/Shrink API,但代价较高)。
    • 数据路由:ES 根据公式 shard = hash(routing) % number_of_primary_shards 来决定文档存储在哪个分片上。如果分片数量变了,这个公式就失效了,导致找不到数据。

2. Replica(副本 / 副本分片)

为了防止硬件故障导致数据丢失,以及提高搜索的吞吐量,ES 允许为每个主分片创建一份或多份拷贝,这些拷贝叫做 Replica Shard(副本分片)

  • 本质:它是主分片的精确复制。
  • 作用
    • 高可用性 (High Availability):如果存放主分片的节点挂了,ES 会自动将对应的副本分片提升(Promote)为新的主分片,确保服务不中断。
    • 提升读取性能 (Read Throughput):搜索请求可以在主分片或副本分片上执行。增加副本数量可以分担查询压力,提高并发读取能力。
  • 关键特性
    • 动态调整:副本的数量可以随时动态修改(通过 Update Settings API)。
    • 反亲和性副本分片永远不会和它的主分片在同一个节点上。如果在同一个节点,一旦该节点挂了,主备全丢,副本就失去了意义。

3. 图解示例

假设我们有一个集群,包含 3个节点
我们创建一个名为 users 的索引,配置为:3个主分片 (P),1个副本 (R)

总共会有 6 个分片实例(3个主 + 3个副本)。ES 会自动将它们均匀分布,可能如下所示:

Node 1 Node 2 Node 3
P0 ✅ (主分片 0)
R0 ✅ (副本 0)
P1 ✅ (主分片 1)
R1 ✅ (副本 1)
P2 ✅ (主分片 2)
R2 ✅ (副本 2)
  • 如果 Node 1 挂了
    • P0 丢失。
    • ES 检测到 Node 2 上有 R0。
    • ES 将 Node 2 上的 R0 提升为新的 P0。
    • 集群状态变黄(Yellow),因为缺少了 R2 和 新的 R0(原本在Node 1上)。
    • 如果 Node 1 恢复或有新节点加入,ES 会重新复制数据补齐副本,集群变绿(Green)。

4. 写入与读取流程的区别

  • 写入 (Write)

    1. 请求发送到协调节点。
    2. 根据路由计算,请求被转发到对应的 主分片 (Primary Shard)
    3. 主分片执行写入。
    4. 如果成功,主分片将请求并行转发给所有的 副本分片 (Replica Shards)
    5. 一旦所有(或满足配置的)副本写入成功,主分片向客户端报告成功。
    • 结论:写入性能主要受限于主分片,且副本越多,写入越慢(因为要同步)。
  • 读取 (Read/Search)

    1. 请求发送到协调节点。
    2. 协调节点通过轮询算法(Round-robin),在主分片和副本分片中选择一个来处理请求(负载均衡)。
    • 结论:副本越多,读取的并发能力越强。

5. 最佳实践与常见问题

Q: 我应该设置多少个分片?

这是一个经典的容量规划问题。没有标准答案,但有经验法则:

  • 分片大小:建议单个分片的大小保持在 10GB 到 50GB 之间。
    • 太小:会导致过多的元数据开销(Lucene segment 合并压力大,JVM 堆内存占用高)。
    • 太大:数据恢复(Rebalance)极慢,且一旦该分片所在节点故障,恢复时间很长。
  • 节点与分片比:通常建议每 1GB 堆内存对应 20-25 个分片。

Q: 我应该设置多少个副本?

  • 开发环境:0 个副本(节省空间)。
  • 生产环境:至少 1 个副本(保证高可用)。
  • 读多写少场景:可以适当增加副本数量(如 2-3 个),以提升查询吞吐量。

Q: 为什么主分片数量不能随便改?

因为 ES 存储文档时是根据 hash(id) % 主分片数 来决定存哪里的。如果存的时候分片数是 5,取的时候分片数变成了 6,取模的结果就不一样了,ES 就不知道去哪个分片找这个数据了。

总结对比

特性 Primary Shard (主分片) Replica Shard (副本分片)
主要目的 存储数据、水平扩展、写入入口 高可用(容灾)、提升读取吞吐量
写入能力 负责处理写操作 被动同步主分片的数据,不直接处理写
读取能力 可以处理读操作 可以处理读操作
数量设置 创建索引时指定,通常不可变 可以随时动态修改
位置限制 不能与对应的主分片在同一节点
性能影响 决定了索引的最大容量和写入并发 副本越多,读越快,但写越慢(同步开销)
右滑查看面试常问