← [ BACK_TO_NOTES ]

Elasticsearch

Elasticsearch 的后端工程主笔记:从倒排索引、Mapping、Analyzer、Segment、Near Real-time Search,到 Shard/Replica、聚合、写入链路、容量与选型边界。

#concept #growing #backend #architecture

[!info] related notes

Elasticsearch

[!abstract] 一句话定位 Elasticsearch 是建立在 Lucene 之上的分布式搜索与分析引擎,擅长全文检索、过滤、相关性排序和聚合。它通常是由业务事实同步出的搜索投影,不应仅因为能存 JSON 就默认成为业务唯一数据库。

核心数据模型

对象含义
Document一个 JSON 文档
Index一组相关文档的逻辑命名空间
Mapping字段类型以及如何索引/查询
Primary Shard文档水平分片,每个文档属于一个 Primary
Replica ShardPrimary 的副本,提供冗余和读能力
SegmentLucene 内部不可变索引段

[!warning] Index 的双重含义 Elasticsearch Index 是文档集合;关系型数据库 Index 是表上的访问结构。两者不能直接类比。

倒排索引

普通存储从文档看词:

Document → Terms

倒排索引从词找到文档:

term "kafka" → doc 12, doc 81, doc 104

因此全文检索不必逐文档扫描正文。实际搜索还会结合词频、字段、长度等信息计算相关性。

Mapping:Text 与 Keyword

text

用于全文检索,通常经过 Analyzer:

Character Filter → Tokenizer → Token Filter → Terms

适合文章标题、正文、描述等自然语言。

keyword

把整个值作为精确 Term,适合:

  • ID;
  • Enum / Status;
  • Tag;
  • Exact Match;
  • Aggregation / Sort。

错误 Mapping 会直接影响检索正确性和资源成本。生产中应优先显式 Mapping / Template,而不是无限依赖动态映射。

Inverted Index 与 Doc Values

Inverted Index
term → documents
→ search / filter

Doc Values
field-oriented values
→ sort / aggregation / scripting

全文检索和聚合使用的主要数据结构不同,因此字段类型也会影响磁盘、Heap 和查询方式。

Lucene Shard 由多个不可变 Segment 构成。新写入先进入内存索引缓冲区,Refresh 后形成可被搜索打开的新 Segment:

Index Request acknowledged
→ in-memory indexing buffer
→ Refresh
→ new Segment becomes searchable

默认情况下,新文档通常在秒级变得可搜索,因此称为 Near Real-time,而不是立即可见。

Write acknowledged ≠ Search immediately sees it

频繁强制 Refresh 会增加 Segment 和 Merge 压力。

Translog、Refresh 与 Flush

  • Refresh:让最近写入对 Search 可见。
  • Translog:为尚未进入安全 Lucene Commit 的操作提供恢复路径。
  • Flush:推进 Lucene Commit 并开始新的 Translog Generation。

它们分别解决搜索可见性与崩溃恢复,不应都笼统理解为“刷盘”。

Shard 与 Replica

Index
├─ Primary Shard 0 → Replica 0
├─ Primary Shard 1 → Replica 1
└─ Primary Shard 2 → Replica 2
  • Primary Shard 数量决定基础数据分布和并行度,标准 Index 创建后不能直接随意修改。
  • Replica 数量可调整,用于冗余和读扩展。
  • 每个 Shard 本质上是独立 Lucene Index,也有 Segment、文件句柄、Heap 元数据和恢复成本。

因此 Shard 不是越多越好。

写入与查询链路

写入

Client
→ Coordinating Node
→ route by document id
→ Primary Shard
→ Replica Shards
→ response

查询

Client
→ Coordinating Node
→ scatter query to relevant shards
→ each shard returns local top results
→ coordinating node merges / reduces
→ response

Shard 数量过多会放大 Scatter-Gather、协调和小文件成本。

Query、Filter 与 Aggregation

  • Query Context:通常参与相关性评分。
  • Filter Context:只判断是否匹配,适合状态、时间、权限等结构化条件。
  • Aggregation:对匹配文档做桶分组、指标统计和分析。

权限过滤应在 Query 层强制执行,不能先返回跨租户结果再让应用“自行忽略”。

更新和删除为什么有成本

Segment 不可变,更新通常等价于“写新版本 + 标记旧文档删除”;旧数据空间要等 Segment Merge 才真正回收。

因此高频小更新、频繁 Refresh 和错误的文档粒度会增加 Merge、I/O 和磁盘放大。

业务事实同步模式

常见架构:

PostgreSQL / MySQL (Source of Truth)
→ Outbox / CDC / Kafka
→ Indexer
→ Elasticsearch (Search Projection)

当索引丢失或 Mapping 变更时,应能从事实层重建,而不是让业务只能依赖 ES 中的副本。

高频生产问题

问题机制治理方向
Mapping Explosion动态字段无限增长显式 Mapping、字段治理
Too Many Shards每个 Shard 有固定成本合理分片、Rollover / ILM
Hot ShardRouting / 数据倾斜调整 Key、Shard 和写入模型
Deep Pagination大 Offset 需要各 Shard 保留大量候选search_after / PIT
Merge Pressure高频写入、删除、RefreshBulk、调 Refresh、容量规划
Heap PressureAggregation、Fielddata、Shard 过多Mapping、Query、节点与内存治理
Unassigned Shard节点、磁盘、水位或分配规则查 Allocation Explain

观测重点

indexing / search latency and rate
rejected operations / thread pools
JVM heap / GC
segment count / merge time
primary and replica shard health
unassigned shards
refresh / flush / translog
node disk watermarks
document and mapping growth

适用与不适用

适合:全文搜索、日志检索、商品/内容搜索、复杂过滤和聚合、可重建派生索引。

不适合默认承担:强事务业务事实、复杂关系约束、高频跨文档原子更新、大对象存储。

面试掌握标准

  • 倒排索引;
  • text、keyword 与 Analyzer;
  • Segment、Refresh 与 NRT;
  • Primary / Replica Shard;
  • 分布式写入与 Scatter-Gather 查询;
  • Mapping Explosion、Too Many Shards、Deep Pagination;
  • ES 为什么通常是派生搜索层;
  • 如何从数据库 + CDC 重建索引。

官方资料

创建于 2026/9/4 更新于 2026/9/4
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本