ES写入和查询过程
目录
ES 的写入过程
[客户端请求]
│
↓
[协调节点(Coordinate Node)] (接收请求,根据路由,决定目标数据节点,目标分片)
│
↓
[主分片(Primary Shard)处理] (分片底层是 Lucene, 以下描述了将数据固化为倒排索引,doc values等多种数据结构)
├─ 1. 写入内存缓冲区 (In-memory Buffer)
├─ 2. 追加事务日志 (Translog)
├─ 3. 定期刷新 (Refresh) → 生成新的Lucene段(不可变)→ 可被搜索
└─ 4. 后台Flush (满足条件时)
├─ 将内存数据写入磁盘
├─ 清空内存缓冲区
└─ 创建新的Translog
│
↓
[副本分片(Replica Shards)同步] (并行处理,确保数据冗余)
│
↓
[返回响应] (ACK确认写入成功)
- 客户端发送请求到协调节点(Coordinator)
- 协调节点将请求路由到主分片(Primary Shard)
- 主分片只要完成上述1,2两步(即写入内存和写入Translog),就会向协调节点返回ACK,再由协调节点返回给客户端(默认情况)
- 同时主分片 并行 将数据同步到副本分片(Replica Shards),默认情况“主分片确认即返回”(
wait_for_active_shards=1
),所以同步操作是异步进行的,如果副本分片同步失败,集群会尝试修复,但是客户端不会感知 - 副本分片完成写入后,向主分片发送ACK(不直接通知协调节点)
- 主分片收到 所有副本的ACK(或满足
wait_for_active_shards
条件)后,才向协调节点返回ACK(强一致性情况,配置wait_for_active_shards
为all
或quorum
,等待全部副本或多数副本) - 协调节点最终将 ACK 返回给客户端
ES 的查询过程
ES 的查询分为两个阶段 Query Phase 和 Fetch Phase。
Query Phase:
- 客户端发起搜索请求,请求先发送到协调节点
- 协调节点解析查询请求,确定查询的索引和索引对应的所有逻辑分片(包括副本分片)集合,如果多索引查询,会合并各索引映射和信息
- 根据负载均衡策略确定具体参与查询的分片,同时还需要实时状态检查(检查分片的可用状态,是否重定位等信息),最后可能包括一些自适应调整,比如响应较慢的分片,触发重试机制,最后将查询请求并发的发送到选择的节点上
- 请求到达分片后,分片会并发搜索多个
Segment
,从倒排索引中查询匹配的文档,计算文档相关性得分,结合得分和Doc Values
获取排序信息,获取到前 N 个文档 ID 和 分数,将该轻量化的结果列表返回给协调节点
Fetch Phase:
- 协调节点合并、排序所有分片返回的结果,最终选取前 N 个结果
- 向相关分片发送文档内容取回请求,获取文档完整内容
- 分片返回完整文档内容(存储在
Stored Fields
中)和元数据 - 协调节点组装最终结果,返回给客户端