Elasticsearch 的写入流程

128 阅读3分钟

1. 客户端请求与路由

  • 请求入口:客户端通过 REST API(如 PUT /{index}/_doc/{id})或 Transport Client 发送文档写入请求。
  • 路由计算:根据文档的 _id(或自定义路由参数)计算目标分片:
shard = hash(_routing) % number_of_primary_shards
  • 文档会被路由到对应的主分片(Primary Shard)
  • 若未指定 _id,Elasticsearch 会自动生成唯一 ID(基于 UUID),并跳过版本冲突检查。

2. 主分片写入

主分片所在节点处理写入请求,步骤如下:

(1) 内存写入(In-Memory Buffer)

  • 文档首先写入 内存缓冲区(In-Memory Buffer) ,此时数据不可被搜索
  • 同时,操作日志(Translog)被同步记录到磁盘(默认 index.translog.durability 为 request,即每次请求都持久化)。

(2) Refresh 操作

  • 触发条件:默认每隔 1秒(可通过 index.refresh_interval 配置)或缓冲区达到阈值。

  • 操作内容

    • 将内存缓冲区的数据生成新的 Lucene Segment,并写入文件系统缓存PageCach(非磁盘)。
    • 新 Segment 被打开后,文档可被搜索(近实时搜索,NRT)。
  • 影响:频繁 Refresh 会生成大量小 Segment,增加后续合并(Merge)压力。

3. Translog 持久化

  • Translog 作用:确保在内存数据未持久化到磁盘时,仍可通过 Translog 恢复数据。

  • 持久化策略

    • request 模式:每次写入请求后同步刷盘(强一致性,性能较低)。
    • async 模式:异步定期刷盘(更高吞吐,但可能丢失部分数据)。
  • Flush 操作

    • 当 Translog 大小达到阈值(默认 512MB,index.translog.flush_threshold_size)或时间间隔(默认 30分钟),触发 Flush:

      • 将内存缓冲区数据写入磁盘,生成新的 Lucene Segment。
      • 清空 Translog,创建新的 Translog 文件。

4. 副本分片同步(Replication)

主分片写入成功后,并行将操作同步到所有副本分片(Replica Shards)

  • 副本分片执行相同的写入流程(内存缓冲区 + Translog)。

  • 写入一致性控制

    • wait_for_active_shards:可配置需等待的副本分片数(如 all1)。
    • 默认仅需主分片成功即可返回响应(consistency 级别为 quorum)。

5. Segment 合并(Merge)

  • 后台任务:定期合并多个小 Segment 为更大的 Segment,优化查询性能。

  • 合并策略

    • Tiered Merge Policy(默认):分层合并,优先合并大小相近的 Segment。
    • Log Byte Size Merge Policy:基于 Segment 总大小的合并。
  • 影响

    • 合并过程消耗 I/O 和 CPU 资源,可能影响写入性能。
    • 合并后删除旧 Segment,释放磁盘空间。

6. 最终持久化(Fsync)

  • 手动触发:调用 _flush API 或满足特定条件时,强制将文件系统缓存中的数据写入磁盘。
  • 作用:确保数据持久化,但通常依赖 Translog 的容错机制即可。

写入流程优化技巧

1. 提升吞吐量

  • 批量写入:使用 _bulk API 减少网络开销。
  • 调整 Refresh 间隔:增大 refresh_interval(如 30s)减少 Segment 生成频率。
  • 关闭副本:写入时临时设置 index.number_of_replicas: 0,写入完成后再恢复。

2. 降低延迟

  • 强制 Refresh:写入后调用 _refresh 使数据立即可查。
  • 缩短 Translog 刷盘间隔:调整 index.translog.sync_interval

3. 容错与一致性

  • 设置 wait_for_active_shards:确保足够副本分片写入成功。
  • 启用 Translog 校验index.translog.durability: request 避免数据丢失

写入流程图

%% RocketMQ事务消息流程图(Mermaid).png

总结

Elasticsearch 的写入流程通过内存缓冲区、Translog、近实时搜索等机制,在性能与可靠性之间实现了平衡。理解其核心步骤(内存写入、Translog、Refresh、副本同步、Segment 合并)及可调参数,是优化写入性能和处理异常场景的关键。