大数据-181 Elasticsearch 段合并与磁盘目录拆解

1. 背景:为什么需要段合并

Elasticsearch 的写入是「追加型」的,索引文档时不会直接更新已有文档,而是:

  1. 新文档写入内存 Buffer
  2. refresh 时,Buffer 内容写入新段(Segment)
  3. 段不可变更(Immutable)

refresh 频率默认 1 秒一次,意味着每秒都会产生新段。段越多,问题越多:

  • 文件句柄占用(每个段需要打开多个文件)
  • 内存开销(每个段有独立数据结构)
  • CPU 消耗(查询时需要合并多个段的結果)
  • 磁盘空间(已删除文档不释放,只做标记)

段合并(Merge)就是在后台把小段并入大段,清理已删除文档。

2. Merge Policy 配置

2.1 核心参数

参数默认值含义
index.merge.policy.floor_segment2MB小于此大小的段会被忽略,不参与合并
index.merge.policy.max_merge_at_once10每次合并最多参与的段数
index.merge.policy.max_merged_segment5GB合并后最大段大小
index.merge.policy.segments_per_tier10每层最少段数(与 max_merge_at_once 配合)

2.2 配置示例

{
  "settings": {
    "index.merge.policy.max_merge_at_once": 20,
    "index.merge.policy.max_merged_segment": "10gb"
  }
}

3. Force Merge

强制合并用于只读/归档场景,手动把段合并成更少的段:

POST /my-index/_forcemerge?max_num_segments=1

注意

  • 会产生大量 I/O,建议在业务低峰期执行
  • 完成后无法回退
  • 只读索引建议用此操作归档

4. ES 数据目录结构

nodes/
  └── 0/
      └── indices/
          └── {index-uuid}/
              └── 0/
                  ├── _state/
                  │   └── state-1.st
                  ├── index/
                  │   ├── _0.cfe
                  │   ├── _0.cfs
                  │   └── _0.si
                  └── translog/
                      └── translog.ckp

4.1 核心文件类型

文件后缀含义
.cfe复合文件入口
.cfs复合文件数据
.si段信息
.docDocValues
.dimBKD 树(地理坐标)
.pos位置信息
.tipTerm Index

5. 总结

  • 段合并由后台线程自动执行
  • 合理配置 Merge Policy 可平衡写入性能与查询效率
  • Force Merge 只适用于只读索引
  • 理解目录结构有助于排查问题