关于 Elasticsearch 的存储原理 ,文章将从 整体架构、底层结构、Lucene 段文件、写入-刷新-合并机制、以及运维经验 五个方面详细说明。
一、总结一句话
Elasticsearch 的数据最终是存储在 Lucene 的倒排索引文件中,按照"写入内存缓冲 → 刷盘生成 segment → 合并优化"的过程持续进行,并通过分片机制分布式存储。
二、存储架构概览
sql
Index(逻辑索引)
├── Shard(逻辑分片) → Primary + Replica
│ ├── Lucene Index(物理索引)
│ │ ├── Segment 文件(多个)
│ │ ├── .fdt、.fdx、.tim、.tip、.doc、.cfs...
-
每个 ES 索引被分成多个 shard,每个 shard 是一个独立的 Lucene 实例。
-
Lucene 中数据被存储为多个 segment(段)文件,每个 segment 是不可变的。
三、底层存储结构:Lucene Segment
Lucene 中常见 segment 文件类型:
文件类型 | 描述 |
---|---|
.fdt |
存储原始字段数据(Field Data) |
.fdx |
文档字段索引 |
.doc |
存储文档元数据 |
.tim / .tip |
倒排索引(Term Info) |
.cfs |
Compound File(合并后统一存放) |
.dvd / .dim |
docValues,用于排序/聚合等 |
一个 segment 一旦生成就不会修改,删除是通过标记 deleted_docs
来实现。
四、写入 → 刷新 → 合并(segment lifecycle)
写入阶段
- 写入先进入 translog + memory buffer(倒排索引缓冲)
- 不立即落盘,仅进入内存和事务日志
刷新(refresh)
- 默认每 1 秒自动触发
- 将 memory buffer 中数据写入 Lucene 新的 segment,此时数据可被查询
flush
- 将 memory buffer 和 translog 强制写入磁盘,并清空 translog
- 避免数据丢失,用于快照、重启恢复
合并(merge)
-
多个小 segment 合并为一个大 segment
-
优化磁盘空间和查询性能(减少文件句柄、IO 开销)
-
可能带来磁盘使用率短暂上升
五、经验与调优
场景 | 现象 | 优化建议 |
---|---|---|
大量 segment 存在 | 查询变慢,句柄过多 | 配置 merge.policy 控制自动合并,或使用 force merge |
写入磁盘慢 | I/O 等待高 | 使用 SSD,合理配置 refresh/flush 间隔 |
数据丢失 | crash 时未写入磁盘 | 开启 translog.durability=async (提高写入)或 request (提高安全) |
冷数据占用空间大 | 老数据 segment 多 | 考虑使用 rollover + ILM 做冷热分离 |
总结一句话
Elasticsearch 的存储底层依赖 Lucene,通过 segment 文件组成倒排索引,并通过写入 → 刷新 → 合并机制确保数据可搜索、可持久、性能可控,熟悉这些原理有助于我们在写入调优、查询性能、集群稳定性方面做出更好的决策。