两件事别混为一谈
refresh 管的是可见性:把内存缓冲里新写入的文档刷成一个新的 Lucene 段,文档从此能被搜到,这正是 Elasticsearch「近实时搜索」的来源。flush 管的是持久化与恢复速度:触发一次 Lucene commit 把已刷新的段落盘,并清掉 translog 里已提交的部分。
基本信息
| 适用版本 | Elasticsearch 7.x / 8.x |
|---|---|
| refresh 默认间隔 | index.refresh_interval 为 1s |
| 关闭自动刷新 | index.refresh_interval 设为 -1 |
| flush 做什么 | Lucene commit + 清空已提交的 translog |
| 相关 API | POST /<index>/_refresh、POST /<index>/_flush |
典型使用场景
- 批量导入:先把 refresh_interval 设为 -1 再灌数据,结束时恢复并手动刷新一次
- 写完立刻要能查到:单条写入用 refresh=true 或 refresh=wait_for,或写后手动 _refresh
- 重建索引收尾:_reindex 完成后手动 _refresh,确认新索引导入结果可查
- 存档与停写:批量任务结束后 flush,缩短后续重启时的恢复时间
- 排查「数据写进去了却搜不到」:先看 refresh_interval 与最近一次 refresh 时间
示例
示例
POST /my-index/_refresh # 立即让新写入的文档可被搜索
PUT /my-index/_settings # 导入期先关掉自动刷新,减少小段
{ "index": { "refresh_interval": "-1" } }
POST /my-index/_bulk?refresh=false # 批量写入不加 refresh
{ ... }
PUT /my-index/_settings # 导入完成后必须恢复,否则新数据永远搜不到
{ "index": { "refresh_interval": "30s" } }
POST /my-index/_refresh # 恢复后手动刷一次,让存量数据立即可查
POST /my-index/_flush # 落盘 + 清空 translog
GET /_cat/indices/my-index?v&h=index,health,docs.count,store.size两个动作对照
| 动作 | 做了什么 | 代价 |
|---|---|---|
| refresh | 内存缓冲刷成可检索段,文档变为可搜索 | 生成小段,段越多后台合并压力越大 |
| flush | Lucene commit 落盘并清空已提交 translog | 磁盘 I/O 上升,换来更快的重启恢复 |
| refresh_interval | 控制自动 refresh 周期,默认 1s | 设 -1 后新文档不可搜,必须手动刷新 |
| refresh=wait_for | 写入请求等待下一次 refresh 完成再返回 | 等待上限受 refresh_interval 影响 |
| translog | 每次写入先追加的日志,保证未 commit 数据可恢复 | flush 前不断增长,占用磁盘 |
写入请求的 refresh 参数有三个常用值:false(默认,不等待)、true(立刻刷新,开销最大)、wait_for(等下一次自动 refresh 完成,批量导入友好)。wait_for 在 refresh_interval 为 -1 时会一直等下去,此时需要显式 _refresh 或其他机制收尾。
数据安全并不依赖 flush:写入先落 translog,节点异常重启后会重放未 commit 的操作。flush 的价值在于把重放量降下来,缩短恢复窗口,所以长跑任务结束后做一次是划算的。
refresh_interval 的大小就是「近实时」延迟的量级:默认 1s 意味着刚写入的文档最多 1 秒后才可能被查出来,这行配置也常在压测时被误判成丢数据。