基于本文回答

播面 播面

文解图解播客视频,多维讲透八股文
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 (副本分片)
主要目的 存储数据、水平扩展、写入入口 高可用(容灾)、提升读取吞吐量
写入能力 负责处理写操作 被动同步主分片的数据,不直接处理写
读取能力 可以处理读操作 可以处理读操作
数量设置 创建索引时指定,通常不可变 可以随时动态修改
位置限制 不能与对应的主分片在同一节点
性能影响 决定了索引的最大容量和写入并发 副本越多,读越快,但写越慢(同步开销)