Elasticsearch分片

wen IT资讯 25

本文目录导读:

Elasticsearch分片

  1. 两种类型的分片
  2. 分片的核心工作原理
  3. 分片数量与副本数量的最佳实践
  4. 分片与节点的关系(关键概念)
  5. 常见问题与陷阱
  6. 调整分片(重要提醒)

Elasticsearch 的分片,这是一个非常核心且关键的概念。分片是 Elasticsearch 将索引数据分布到集群中多个节点上的基本单元。

可以把一个索引想象成一个巨大的数据库表,当这个表的数据量太大,或者查询压力太高时,单台机器无法胜任,分片就是将这个大表水平切割成多个更小的、独立的部分,每个部分就是一个分片,每个分片本身就是一个功能完整的 Lucene 索引

下面为你详细解析 Elasticsearch 分片的核心要点、工作原理、最佳实践以及常见问题。

两种类型的分片

Elasticsearch 中有两种分片,理解它们的区别至关重要:

  1. 主分片 (Primary Shard)

    • 定义:数据写入和读取的原始入口点。
    • 作用:负责处理索引和查询请求,它是数据的“正本”。
    • 数量在创建索引时设定,并且一经设定,无法修改(除非重建索引)。 这是一个非常重要的设计决策。
  2. 副本分片 (Replica Shard)

    • 定义:主分片的精确拷贝。
    • 作用
      • 高可用性:当承载主分片的节点宕机时,副本分片可以自动提升为新的主分片,保证集群不丢失数据,服务不中断。
      • 提高查询吞吐量:副本分片可以响应查询请求,高并发查询时,主、副本分片可以并行工作,大大提升搜索性能。
    • 数量可以随时动态调整,可以设置副本数为 0(节省空间,但无容错),也可以设置为 3(容错性高,但占用更多磁盘和网络资源)。

分片的核心工作原理

  1. 数据写入流程

    • 当你向一个索引写入文档时,Elasticsearch 会通过路由算法(默认基于文档 _id 的哈希值)计算该文档应该放入哪个主分片
    • 公式:shard_num = hash(_routing) % num_primary_shards
    • 文档被写入对应的主分片,随后主分片将此操作同步到其所有副本分片,只有当主分片和所有副本分片都完成写入(或配置的 wait_for_active_shards 条件满足)后,写入请求才会成功返回。
  2. 数据查询流程

    • 一个搜索请求(term, match)会广播到索引的所有主分片或副本分片上(默认是“轮询”主和副本)。
    • 每个分片独立执行查询,返回自己分片内的匹配结果(即“局部结果”)。
    • 协调节点负责收集所有分片返回的局部结果,进行全局合并、排序、分页,最后将最终结果返回给客户端。

分片数量与副本数量的最佳实践

这是 Elasticsearch 使用中最容易出问题的地方。

主分片数量 (Primary Shards)

  • 原则设大不设小,但也不能太大
  • 设定时机:创建索引时 PUT my-index { "settings": { "number_of_shards": 3 } }
  • 推荐范围:根据你的数据量和节点数,建议每个分片的大小控制在 10GB 到 50GB 之间,最大不要超过 100GB。
    • 分片太小(< 1GB):会导致“分片过多”的问题,集群管理开销(元数据、脑裂风险、搜索并发问题)巨大。
    • 分片太大(> 100GB):故障恢复速度慢,重新平衡数据耗时长,搜索性能会因 I/O 瓶颈而下降。
  • 计算公式参考
    • 预估总数据量:500GB。
    • 目标分片大小:30GB。
    • 所需主分片数量 ≈ 500GB / 30GB ≈ 16 ~ 17 个,考虑到未来的增长,你可以设成 20 个,这是一个经验值,需要根据实际硬件(磁盘和内存)调整。

副本分片数量 (Replica Shards)

  • 原则与作用性能 + 容错
  • 设定时机:随时可以调整 PUT my-index/_settings { "index.number_of_replicas": 1 }
  • 推荐值
    • 生产环境:至少设置为 1(保证任何一台机器宕机,数据不丢,查询不中断)。
    • 高可用/高查询场景:如果查询压力极大,可以设置为 2 或 3,但要注意,副本数增加会占用等倍的磁盘空间和网络带宽。
    • 开发/测试环境:可以设置为 0,节省资源。

分片与节点的关系(关键概念)

  • 同一个分片的主副本不能存在于同一个节点上,这是 Elasticsearch 高可用的核心保证,如果主副本都在同一节点,该节点宕机,数据就全丢了。
  • 尽量让分片均匀分布在所有节点上,这样才能充分利用集群的并行计算能力和存储空间。

举例:一个索引有 4个主分片,2个副本 (总共 4 * (1+2) = 12 个分片实体),运行在 3个节点 的集群上。

  • 系统会自动将 12 个分片实体(4主 + 8副)均衡地分布到 3 个节点上(每个节点约 4 个分片实体)。
  • 如果其中 1 个节点宕机,剩余的 2 个节点会检测到,副本分片会自动提升为新的主分片,集群仍然正常工作(只是副本数暂时变成 1 甚至 0)。

常见问题与陷阱

  1. 分片数过大

    • 问题:集群元数据庞大,每个分片都需要占用文件句柄、内存、线程,搜索时协调节点需要向大量分片发起请求,网络开销和合并开销剧增。
    • 解决方法:合理规划分片数;如果已经建立,可以创建新索引(调整分片数),使用 Reindex API 将老数据迁移过去。
  2. 分片数过小

    • 问题:单个分片过大(> 200GB),索引和查询性能急剧下降;无法充分利用多台服务器资源。
    • 解决方法:同样通过 Reindex 重建索引。
  3. 路由与分片不均衡

    • 如果使用了自定义 routing 值(例如按 user_id 路由),没有合理设置,可能导致某些分片巨大,某些分片很小(“热点”问题)。
    • 解决方法:检查路由策略,或者调整分片数使其足够多来分散热点。
  4. 分片与节点数量的平衡

    • 公式建议:节点数 × (副本数 + 1) 要不大于 主分片数,才能保证数据的均匀分布,5个节点,1个副本,则主分片数建议≥ 5×(1+1)=10。 否则,理论上有些节点会空闲。

调整分片(重要提醒)

  • 无法直接修改number_of_shards 一旦索引创建即锁定,无法变更。
  • 如何修改
    • Reindex API:创建一个新索引(设置好 number_of_shards),将数据从旧索引通过 Reindex 迁移过去,然后将别名指向新索引,这是生产环境最标准的做法
    • Split API(Elasticsearch 6.1+):可以将主分片数量翻倍,但前提是旧索引的 index.number_of_routing_shards 设置合理。
    • Shrink API(Elasticsearch 5.0+):可以将主分片数量减少到某个因子,例如从 8 个缩小到 4 个或 2 个。
  • 分片 = 数据的基本搬运和搜索单元
  • 主分片数量 = 固定不可变副本数量 = 可随时调整
  • 每个分片建议 10~50GB,这是一个经验法则。
  • 副本 = 性能 + 容错
  • 集群规模(节点数)和分片数要匹配

理解分片是掌握 Elasticsearch 性能调优和高可用架构的基石,在实际生产环境中,一定要在设计之初就做好规划,避免后期遇到因分片不合理导致的性能瓶颈或运维难题。

抱歉,评论功能暂时关闭!