Skip to content

ES的写入流程是什么样的?

ES 写入流程概述

  • 定义
  • ES 的写入流程是将文档(如 JSON)索引到分片的过程,涉及分片分配、数据存储和同步。
  • 核心步骤
  • 协调节点接收请求并路由。
  • 主分片写入数据。
  • 副本分片同步写入。
  • 确认返回结果。

问题解答

  1. 发请求首先是发到哪个节点上的?
  2. 发到任意节点(通常是协调节点),由其路由到正确的主分片所在节点。
  3. 写请求都会到主节点上吗?
  4. 写请求不直接到主节点(Master Node),而是到主分片所在的数据节点,主节点仅管理元数据。
  5. 只要写一个主分片成功后,请求就结束了吗?
  6. 否,默认需等待所有副本分片写入成功(可配置)。
  7. 副本分片是否需要保证完全写入?
  8. 默认需全部副本写入,但可通过 write_consistencywait_for_active_shards 调整。
  9. ES 是最终一致性还是强一致性?
  10. ES 是最终一致性,写入后近实时(NRT)可见,副本同步可能有短暂延迟。

核心点

  • ES 写入依赖协调节点路由、主分片优先、副本同步,默认追求一致性但允许配置灵活性。

1. ES 写入流程详解

步骤分解

  1. 协调节点接收请求
  2. 客户端发送写请求(如 PUT /index/_doc/1)到任意 ES 节点。
  3. 该节点作为协调节点,解析请求。

  4. 路由到主分片

  5. 协调节点根据文档 _id 或路由规则(如 routing 参数)计算分片:
    • 公式:shard = hash(_id) % number_of_primary_shards
  6. 请求转发到主分片所在的数据节点。

  7. 主分片写入

  8. 主分片节点执行:

    • 验证:检查文档格式、映射。
    • 索引:写入内存 Buffer 和 Translog(事务日志)。
    • Lucene Segment:数据暂存内存。
  9. 副本分片同步

  10. 主分片将请求并行转发到所有副本分片。
  11. 副本执行相同写入(Buffer + Translog)。
  12. 默认需所有副本确认成功。

  13. 确认返回

  14. 主分片收集副本响应,通知协调节点。
  15. 协调节点返回客户端成功(HTTP 200)或失败。

  16. 刷新(Refresh)

  17. 内存 Buffer 定期(默认 1 秒)生成 Lucene Segment,数据可搜索(近实时)。
  18. Translog 持久化,保障可靠性。

图示

客户端 --> [协调节点] --> [主分片] --> [副本 1, 副本 2]
                   |           |
                   v           v
              [Buffer]    [Translog]
                   |           |
                   v           v
              [Segment]  [磁盘持久化]

2. 问题逐一解答

(1) 发请求首先是发到哪个节点上的?

  • 请求发到集群中任意节点(通常客户端通过负载均衡器访问)。
  • 该节点作为协调节点,负责:
    • 解析请求。
    • 计算分片位置。
    • 转发到主分片所在节点。
  • 示例
curl -X PUT "http://node1:9200/users/_doc/1" -d '{"name":"Alice"}'
  • node1 是协调节点,路由到主分片。

(2) 写请求都会到主节点上吗?

  • 不会。写请求到主分片所在的数据节点,而非主节点(Master Node)。
  • 主节点作用
    • 管理集群元数据(如创建索引、分片分配)。
    • 不直接处理数据写入。
  • 区分
    • 主节点:集群管理。
    • 主分片:数据写入入口。
  • 示例
  • users/_doc/1,协调节点路由到主分片(可能在 node2),主节点不参与。

(3) 只要写一个主分片成功后,请求就结束了吗?

  • 默认不会。ES 默认要求主分片和所有副本分片都写入成功后才返回成功。
  • 配置参数
    • wait_for_active_shards
    • 默认:所有主分片和副本(all)。
    • 可设为 1(仅主分片),加速响应但牺牲一致性。
  • 流程
    • 主分片写成功后,异步同步副本。
    • 收集副本确认后,返回客户端。
  • 示例
PUT /users/_doc/1?wait_for_active_shards=1
{
  "name": "Alice"
}
  • 仅主分片成功即返回。

(4) 副本分片是否需要保证完全写入?

  • 默认需要,但可配置。
  • 机制
    • 主分片写成功后,副本并行写入。
    • 若副本失败(超时或宕机),请求可能失败。
  • 配置灵活性
    • wait_for_active_shards:指定所需成功分片数。
    • 例:设为 2,主分片 + 1 副本成功即可。
  • 容错
    • 副本失败不影响主分片,主节点稍后重分配副本。
  • 示例
  • 1 主分片 + 2 副本,默认需 3 个都成功。

(5) ES 是最终一致性还是强一致性?

  • ES 是最终一致性
  • 原因
    • 写入主分片后,副本异步同步,可能有短暂延迟(毫秒到秒级)。
    • 刷新(Refresh)后数据才可搜索(默认 1 秒)。
  • 表现
    • 近实时(NRT):写入后需等待刷新。
    • 副本可能落后主分片。
  • 强一致性支持
    • 配置 refresh=wait_for,等待数据可见。
    • 例:
PUT /users/_doc/1?refresh=wait_for
{
  "name": "Alice"
}
  • 降低性能,慎用。
  • 结论
  • 默认最终一致性,适合高吞吐场景。

3. 写入流程优化

  • 批量写入
  • 使用 _bulk API 减少请求。
POST /_bulk
{ "index": { "_index": "users", "_id": "1" } }
{ "name": "Alice" }
{ "index": { "_index": "users", "_id": "2" } }
{ "name": "Bob" }
  • 调整刷新间隔
  • 默认 1s,可设为 30s 提高吞吐:
PUT /users/_settings
{
  "index": {
    "refresh_interval": "30s"
  }
}
  • 分片数
  • 平衡主分片和副本数,避免过载。

4. 延伸与面试角度

  • 与搜索
  • 写入性能影响搜索实时性。
  • 实际应用
  • 日志:高吞吐写入,接受最终一致性。
  • 电商:商品索引需快速可见。
  • 调试
  • _cat/segments 查看 Segment。
  • _cat/shards 检查分片状态。
  • 面试点
  • 问“流程”时,提协调和分片。
  • 问“一致性”时,提最终一致性。

总结

ES 写入流程从协调节点路由到主分片,同步副本后返回,默认需全部分片成功。请求不直接到主节点,仅主分片成功不结束,副本写入可配置。ES 是最终一致性,适合高性能场景。面试时,可提流程或配置优化,展示理解深度。