← 返回题目列表

Elasticsearch 的 translog、flush 和 segment merge 有什么关系?

高频 困难 第 19 / 30 题 更新于 2026/07/29
Elasticsearchtranslogflushsegment merge写入原理

简化版

ES 写入先进入内存 buffer 和 translog,refresh 会把 buffer 生成可搜索 segment,但不等于持久化提交;flush 会执行 Lucene commit 并开启新的 translog;segment merge 会把多个小 segment 合并成大 segment,减少查询开销和删除标记。refresh 管可搜索,flush 管提交点和 translog 清理,merge 管段整理。

详细版

写入链路可以简化为:

index request -> indexing buffer + translog -> refresh -> new segment searchable
                         -> flush -> Lucene commit + new translog
                         -> merge -> small segments become larger segments

面试要区分几个动作:refresh 让数据近实时可搜;translog 用于故障恢复;flush 建立持久提交点并裁剪 translog;merge 是后台整理 Lucene segment,清理删除标记、减少小段数量,但会消耗 I/O。不要把 refresh、flush、fsync、merge 混成一件事。

完整版教学

一、ES 写入不是立刻变成最终大文件

Elasticsearch 底层基于 Lucene。文档写入后,不是每条都马上落成一个稳定的大索引文件。为了吞吐,它会先进入内存结构,同时写 translog 保障恢复。

简化链路:

client index
  -> primary shard
  -> indexing buffer
  -> translog
  -> replica

这样既能提高写入速度,又能在节点异常后通过 translog 恢复未提交的数据。

记忆钩子:refresh 管看见,flush 管提交,merge 管整理。

二、refresh 让文档近实时可搜索

refresh 会把内存 buffer 中的数据打开成新的 segment,使其可以被搜索。默认情况下 ES 是 near real-time,而不是每次写入立即可搜。

T0 write doc
T0.2 search maybe not found
T1 refresh
T1.1 search found

这解释了为什么写入成功后马上搜索可能查不到。可以用 refresh=wait_for 等待下一次 refresh,但高频使用会影响写入吞吐。

refresh 不是完整持久化提交,它主要解决“可搜索性”。

三、translog 用于故障恢复

translog 是事务日志。写入请求在进入内存 buffer 的同时也写入 translog。如果节点在 Lucene commit 前崩溃,重启时可以从 translog 重放操作。

可以类比数据库 redo log,但不要完全等同。ES 的 translog 与 Lucene segment、flush 策略配合工作。

last commit point
  + translog operations after commit
  = recoverable latest shard state

如果没有 translog,最近写入但尚未提交的内容可能在崩溃后丢失。

四、flush 建立 Lucene commit 并裁剪 translog

flush 会触发 Lucene commit,把当前 segment 状态形成提交点,并开启新的 translog。旧 translog 中已被 commit 覆盖的操作就可以被清理。

before flush:
commit A + translog[op1, op2, op3]

after flush:
commit B includes op1..op3 + new empty translog

flush 太频繁会增加 I/O;太久不 flush,translog 过大,恢复时间可能变长。ES 会根据阈值自动管理,通常不需要业务频繁手动 flush。

五、segment merge 解决小段过多和删除标记

Lucene segment 写入后基本不可变。更新和删除并不是原地修改,而是写新版本或打删除标记。随着 refresh 增多,小 segment 会越来越多。

merge 会在后台把多个小 segment 合并成更大的 segment,同时清理被删除的文档。

seg1 + seg2 + seg3
  -> merge
seg_big

merge 能改善查询效率、减少文件数量,但会消耗 CPU、磁盘 I/O 和临时磁盘空间。写入高峰时 merge 压力可能导致整体变慢。

六、refresh、flush、merge 的区别要能一表说清

动作主要目的影响
refresh让新数据可搜索产生新 segment,影响近实时
flush创建 commit,清理 translog影响恢复边界和 I/O
merge合并 segment,清理删除标记影响查询效率和磁盘 I/O

如果面试官问“为什么写入后搜不到”,答案通常是 refresh;问“崩溃后怎么恢复”,答案涉及 translog;问“删除后磁盘为什么没立刻降”,答案涉及 segment merge。

七、常见误区与追问

  • 误区:refresh 就是把数据安全落盘。 refresh 主要让数据可搜索,持久提交边界要看 flush 和 translog。
  • 误区:flush 会让数据立刻可搜索。 可搜索性主要由 refresh 决定,flush 关注 commit 和 translog。
  • 误区:删除文档后磁盘马上释放。 删除通常先打标记,segment merge 后才真正清理空间。
  • 追问:为什么 refresh 太频繁会影响写入? 它会产生更多小 segment,增加后续 merge 压力。
  • 追问:translog 太大有什么问题? 节点恢复时需要重放更多操作,恢复时间可能变长。
  • 追问:force merge 能不能随便跑? 它很耗 I/O,通常只适合只读或低峰索引,不适合热写索引频繁执行。

八、加强记忆

ES 写入链路记成“三个动作分三件事”:refresh 让新文档可搜索,所以解释近实时;translog 记录未提交写入,所以解释崩溃恢复;flush 建 commit 并清理 translog;merge 合并小 segment 并清理删除标记,所以解释磁盘和查询性能。把这几件事分开,很多 ES 写入、可见性和磁盘问题就能讲清楚。