写点什么

大数据 -181 Elasticsearch 段合并与磁盘目录拆解:Merge Policy、Force Merge、Shard 文件结构一文搞清

作者:武子康
  • 2025-12-12
    山东
  • 本文字数:2728 字

    阅读完需:约 9 分钟

大数据-181 Elasticsearch 段合并与磁盘目录拆解:Merge Policy、Force Merge、Shard 文件结构一文搞清

TL;DR

  • 场景:refresh 频繁产生小段,段数暴涨拖慢搜索;同时想看懂 ES 数据目录与 Lucene 文件

  • 结论:段合并是后台常态动作;手动合并用 _forcemerge,且必须按版本区分可调项与风险

  • 产出:可复用的 merge 调优清单 + shards/indices/_state/translog/index 目录定位方法


版本矩阵


索引文档存储段合并

段合并机制

由于自动刷新流程每秒创建一个新的段,这样会导致短时间内的段数量暴增。而段数目太多会带来较大的麻烦,每一个段都会消耗文件句柄、内存、CPU 运行周期。更重要的是,每个搜索请求必须轮流检查每个段,所以段越多,搜索也就越慢。


Elasticsearch 通过在后台进行段合并来解决这个问题,小的段合并到大的段,然后这些大的段被合并到更大的段,段合并的时候会将那些旧的已删除文档从文件系统中清除,被删除的文档(或被更新文档的旧版本)不会拷贝到新的大段中。启动段合并在进行索引和搜索时会自动进行,这个流程像在下图中提到的一样工作:


  • 第一步:当索引的时候,刷新(refresh)操作会创建新的段并将段打开以供搜索使用

  • 第二步:合并进程选择一小部分大小相似的段,并且在后台将他们合并到更大的段中,这并不会中断索引和搜索。


两个提交了的段和一个未提交的段正在合并到一个更大的段:



第三步:合并完成时的活动:


  • 新的段被刷新(flush)到了磁盘,写入一个包含新段且排除旧的和较小的段的新提交点

  • 新的段被打开用来搜索

  • 老的段被删除一旦合并结束,老的段被删除



合并大的段需要消耗大量的 I/O 和 CPU 资源,如果任其发展会影响搜索性能,Elasticsearch 在默认情况下会对合并流程进行资源限制,所以搜索仍然有足够的资源很好的执行。默认情况下,归并线程的限速配置:indices.store.throttle.max_bytes_per_sec 是 20MB。对于写入量较大,磁盘转速较高,甚至使用 SSD 盘的服务器来说,这个限速是明显过低的。对于 ELK Stack 应用,建议可以适当调大到 100MB 或者更高。


PUT /_cluster/settings{  "persistent" : {    "indices.store.throttle.max_bytes_per_sec" : "100mb"  }}
复制代码


用于控制归并线程的数目,推荐设置为 CPU 核心数的一半,如果觉得自己磁盘性能跟不上,可以降低配置,免得 IO 性能瓶颈。(index.merge.scheduler.max_thread_count)

归并策略

归并策略 policy 归并线程是按照一定的运行策略来挑选 Segment 进行归并的,主要有以下的几条:


  • index.merge.policy.floor_segement 默认 2MB,小于这个大小的 Segment,优先被并归

  • index.merge.policy.max_merge_at_once 默认一次最多归并 10 个 Segment

  • index.merge.policy.max_merge_at_once_explicit 默认 optimize 时一次最多归并 30 个 Segment

  • index.merge.policy.max_merged_segment 默认 5GB,大于这个大小的 Segment,不用参与归并,optimize 除外。

Optimize API

Optimize API 大可看做强制合并 API,它将一个分片强制合并到 max_num_segments 参数指定大小的段数目,这样做的意图是减少段的数量(通常减少到一个),来提升性能。在特定情况下,使用 OptimizeAPI 颇有益处。例如在日志这种用例下,每天、每周、每月的日志被存储在一个索引中。老的索引实质上是只读的,它们也并不太可能发生变化,在这种情况下,使用 Optimize 优化老的索引,将每一个分片合并为一个单独的段就很有用了,这样既可以节省资源,也可以搜索更加迅速:


POST /Logstash-2024-08/_optimize?max_num_segments=1
复制代码

存储文件详解

信息查看


通过 ES-Head 插件可以查看到一个索引分片的信息,图中一个绿色的方块就代表一个分片 Shard。ES 使用 Lucene 来处理 Shard 级别的索引和查询,因此数据目录中的文件由 Elasticsearch 和 Lucene 共同编写。Lucene 负责编写和维护 Lucene 索引文件,而 Elasticsearch 在 Lucene 之上编写与功能相关的元数据,例如字段映射,索引设置和其他集群元数据,用户和支持功能由 Elasticsearch 提供。

存储目录

我们登录到服务器上,进入到 ES 集群的数据存储目录中,根据我们之前配置好的服务


cd /opt/servers/es/data/nodes/0
复制代码


执行结果如下图所示:



我们进入 indices 目录,这个目录下的数据有:


root@h121:/opt/servers/es/data/nodes/0# cd indices/root@h121:/opt/servers/es/data/nodes/0/indices# lltotal 28drwxrwxr-x 7 es_server es_server 4096 Aug 15 13:50 ./drwxrwxr-x 4 es_server es_server 4096 Aug 15 10:14 ../drwxrwxr-x 4 es_server es_server 4096 Aug 15 11:50 GFUQVFGeR1OMxYpP84kADw/drwxrwxr-x 4 es_server es_server 4096 Aug 15 10:14 nP7CcjJqRGyTSRZFe-ws7Q/drwxrwxr-x 3 es_server es_server 4096 Aug 15 13:50 pLcZj7mpQZ2sj489LCI8PA/drwxrwxr-x 6 es_server es_server 4096 Aug 15 10:43 ppzCzxaxQAegLEM7C3W-ng/drwxrwxr-x 4 es_server es_server 4096 Aug 15 10:14 wF9_Ay68Qhyx8X89TRNl0Q/root@h121:/opt/servers/es/data/nodes/0/indices# 
复制代码


对应的截图如下图所示:



如何找到它们的对应关系呢?可以在 ES-Head 中,点击索引的 Info => IndexStatus => 弹窗中有一个 UUID,这个就是我们需要的值,对应的关系如下图所示:



我们需要的是进入这个目录:(你的和我的不一样):


cd ppzCzxaxQAegLEM7C3W-ng
复制代码


目录当中的内容如下图所示:



我们对上述的内容进行解释:


  • 0、1、3 是标识 shard 编号

  • _state 存储了索引状态,包括 setting,mapping 等文件


进入_state 目录,查看当前目录下的内容,如下图所示:


cd _state
复制代码


执行结果如下图:



我们回到上一级,回到刚才的数字编号目录(0、1、3 文件夹)


cd ..
复制代码


执行结果如下,有 0、1、3,我们随便进入一个



cd 0
复制代码


我们进入文件夹之后,可以看到下面有这些内容:



我们进行解释:


  • index ES 的数据目录

  • _state 当前 shard 的信息,比如是主、副分片等信息

  • translog 保证数据写入的安全事务日志数据


我们进入 index 数据目录:


cd indexll
复制代码


可以查看到如下的内容:



我们对当中的文件内容进行解释:


错误速查

其他系列

🚀 AI 篇持续更新中(长期更新)

AI 炼丹日志-29 - 字节跳动 DeerFlow 深度研究框斜体样式架 私有部署 测试上手 架构研究,持续打造实用 AI 工具指南!AI 研究-132 Java 生态前沿 2025:Spring、Quarkus、GraalVM、CRaC 与云原生落地🔗 AI模块直达链接

💻 Java 篇持续更新中(长期更新)

Java-180 Java 接入 FastDFS:自编译客户端与 Maven/Spring Boot 实战 MyBatis 已完结,Spring 已完结,Nginx 已完结,Tomcat 已完结,分布式服务已完结,Dubbo 已完结,MySQL 已完结,MongoDB 已完结,Neo4j 已完结,FastDFS 已完结,OSS 正在更新... 深入浅出助你打牢基础!🔗 Java模块直达链接

📊 大数据板块已完成多项干货更新(300 篇):

包括 Hadoop、Hive、Kafka、Flink、ClickHouse、Elasticsearch 等二十余项核心组件,覆盖离线+实时数仓全栈!大数据-278 Spark MLib - 基础介绍 机器学习算法 梯度提升树 GBDT 案例 详解🔗 大数据模块直达链接

发布于: 刚刚阅读数: 12
用户头像

武子康

关注

永远好奇 无限进步 2019-04-14 加入

Hi, I'm Zikang,好奇心驱动的探索者 | INTJ / INFJ 我热爱探索一切值得深究的事物。对技术、成长、效率、认知、人生有着持续的好奇心和行动力。 坚信「飞轮效应」,相信每一次微小的积累,终将带来深远的改变。

评论

发布
暂无评论
大数据-181 Elasticsearch 段合并与磁盘目录拆解:Merge Policy、Force Merge、Shard 文件结构一文搞清_Java_武子康_InfoQ写作社区