ElasticSearch底层原理

一句话总览(先给你大脑一个地图)

Elasticsearch = 分布式搜索引擎
本质 = Lucene(倒排索引) + 分片 + 副本 + 协调节点

核心思想只有一句:

用倒排索引,把“全文搜索”变成“词 → 文档ID”的快速查找


一、ES 的数据是怎么存的?(从磁盘说起)

1️⃣ Lucene 才是底层王者

Elasticsearch 不是自己做搜索的,它只是:

  • 封装 Lucene
  • 管理分布式(分片、副本)
  • 提供 REST API

👉 真正干活的是 Lucene


2️⃣ Lucene 的核心:倒排索引(Inverted Index)

传统数据库(B+Tree)

docId -> 内容

倒排索引(搜索友好)

词 -> [docId1, docId2, docId3]

例子:

文档ID 内容
1 Java is powerful
2 Java and Elasticsearch
3 Elasticsearch is fast

倒排索引:

java -> [1,2]
elasticsearch -> [2,3]
is -> [1,3]

👉 搜索速度本质上是:
查词典 + 合并 docId 集合


二、Index / Shard / Segment 的真实关系(重点)

这是面试必问,很多人都说不清。

1️⃣ Index ≠ 一个文件

Index
 ├── Shard 0
 │    ├── Segment A
 │    ├── Segment B
 ├── Shard 1
 │    ├── Segment C

概念层级

层级 本质
Index 逻辑概念
Shard Lucene Index
Segment 不可变的索引文件

2️⃣ Segment:为什么是不可变的?

这是 ES 性能的根基

好处

  • 不需要加锁(读性能极强)
  • 文件直接 mmap
  • 支持 OS PageCache

代价

  • 删除 ≠ 真删
  • 更新 = 删旧 + 新增

👉 ES 没有“update”,只有“delete + insert”


3️⃣ Segment 合并(Merge)

随着写入:

  • Segment 越来越多
  • 查询会变慢

于是后台会:

  • 合并小 segment
  • 生成大 segment
  • 旧 segment 被标记删除

⚠️ merge 很吃 IO 和 CPU


三、写入原理(Index 一条数据发生了什么)

这是高频面试题

1️⃣ 写入流程(完整)

请求
 ↓
协调节点
 ↓
路由到 Primary Shard
 ↓
写入内存 buffer
 ↓
写入 translog
 ↓
返回成功

2️⃣ 为什么要 translog?

因为:

  • 内存 buffer 会丢
  • segment 还没落盘

translog = ES 的 WAL

先写日志 → 再异步刷盘

崩溃恢复靠它。


3️⃣ refresh & flush 的区别(重点)

refresh(默认 1s)

  • buffer → segment
  • 数据可被搜索
  • 不落盘

flush

  • segment 落盘
  • 清空 translog

👉 能搜到 ≠ 已持久化


四、查询原理(搜索是怎么跑的)

1️⃣ Query vs Fetch 两阶段

第一阶段:Query

  • 每个 shard 执行查询
  • 返回 docId + score(TopN)

第二阶段:Fetch

  • 汇总 docId
  • 回 shard 拉取 _source
  • 返回给客户端

2️⃣ 为什么分页深了会慢?

from + size 的代价:

  • 每个 shard 都要算 from + size
  • 丢弃前面大量数据

👉 深分页 = 灾难

正确方案

场景 方案
翻页 search_after
导出 scroll
前端 限制页数

五、相关度打分(BM25)

ES 默认算法:BM25

核心因素:

  1. 词频 TF
  2. 逆文档频率 IDF
  3. 字段长度归一化

本质公式(理解即可):

score ≈ TF * IDF * norm

👉 为什么 keyword 不参与评分?

  • 因为它不分词
  • 本质是精确匹配

六、分布式核心:Shard & Replica

1️⃣ 为什么要分片?

  • 单机磁盘有限
  • 单机 CPU 有限

Shard 本质:

一个 shard = 一个 Lucene Index


2️⃣ Primary & Replica

  • Primary:写
  • Replica:读 + 容灾

写流程:

写 Primary
 ↓
同步 Replica
 ↓
返回成功

3️⃣ 为什么副本也能查?

因为:

  • segment 是不可变的
  • replica 结构完全一致

👉 ES 天生支持读扩展


七、为什么 ES 不适合事务?

因为它的设计目标是:

能力 是否支持
强一致
事务
高并发搜索
近实时

ES 是 Near Real-Time(NRT)


八、面试官最爱追问(你必须会)

我直接给你标准回答方向

Q1:ES 为什么比 MySQL 快?

倒排索引 + 顺序 IO + mmap + 不可变 segment

Q2:delete/update 为什么慢?

标记删除 + segment merge

Q3:为什么不建议 shard 太多?

shard = Lucene Index,资源消耗大

Q4:ES 会丢数据吗?

refresh 前可丢,translog 保证 crash 恢复


九、一句工程级总结(记住)

ES 的本质是:
用 Lucene 的倒排索引做全文搜索,
用 shard + replica 做分布式,
用 refresh 实现近实时。

posted @ 2025-12-22 16:31  中登程序猿  阅读(1)  评论(0)    收藏  举报