基于本文回答
0
评论

Scroll API 和 Search After 的区别及适用场景?

知识点图片

在 Elasticsearch 中,当我们需要获取大量数据(Deep Pagination,即深度分页)时,标准的 from + size 方式在数据量超过 10,000 条时会失效且性能极差。Scroll APISearch After 是解决这一问题的两种主要机制。

以下是两者的详细对比、核心区别及适用场景。


1. 核心概念简述

Scroll API (滚屏快照)

  • 原理:类似于传统数据库的游标(Cursor)。它会在搜索开始时创建一个索引的快照(Snapshot)
  • 机制:Elasticsearch 会在服务端维护一个“搜索上下文”(Search Context),即使在查询过程中有新数据写入或旧数据删除,Scroll 依然只能看到快照建立时的数据。
  • 现状:在 Elasticsearch 7.x 及更高版本中,官方已不再推荐用于实时用户请求,并建议用 Search After + PIT (Point In Time) 替代。

Search After (游标分页)

  • 原理:基于上一页最后一条数据的排序值(Sort Values)来检索下一页数据。
  • 机制:它是无状态的(Stateless)。每一次查询都是独立的,它告诉 ES:“请给我排在 [值A, 值B] 之后的数据”。
  • 现状:这是官方推荐的深度分页方式,特别是结合 PIT (Point In Time) 使用时,可以完美替代 Scroll。

2. 详细对比

特性 Scroll API Search After
状态维护 有状态。服务端需维护上下文,占用内存资源。 无状态。服务端不维护游标位置,客户端自行控制。
数据一致性 强一致性(快照)。查询期间的数据变更不可见。 弱一致性(实时)。默认情况下,翻页过程中如果数据变动,可能导致数据重复或丢失(除非配合 PIT 使用)。
资源消耗 。随着并发量增加,维护 Context 的成本极高。 。仅需计算排序和过滤,无额外上下文开销。
排序要求 无强制要求。 必须有唯一排序字段(通常用 _id 作为 Tie-breaker),否则分页会乱。
灵活性 只能向后滚动,不支持跳页,不支持修改查询条件。 只能向后翻页(逻辑上),不支持随机跳页,但支持更改后续逻辑。
最大限制 max_open_scroll_context 限制。 无硬性限制。
推荐版本 旧版本常用,新版已不推荐。 新版本推荐标准

3. 适用场景

Scroll API 适用场景

虽然官方不再推荐,但在以下场景中(尤其是旧版本 ES)仍然可见:

  1. 全量数据导出/迁移:例如将 ES 索引的数据全部导出到 Hadoop、Spark 或另一个 ES 集群。
  2. 离线批处理任务:脚本在后台跑数据,不需要实时响应用户,且必须保证处理过程中数据视图的一致性(不希望处理到一半数据变了)。
    • 注意:如果你的 ES 版本较新,请使用 Search After + PIT 替代此场景。

Search After 适用场景

  1. C端/B端 业务系统的深度分页:例如手机 App 的“无限下拉”加载更多(Infinite Scroll)。
  2. 实时数据查询:用户需要看到最新的数据,且数据量可能很大。
  3. 替代 Scroll 的全量导出(需配合 PIT):在 ES 7.10+ 版本后,使用 Search After 配合 Point In Time (PIT) API,既能获得 Scroll 的“快照”一致性能力,又能避免 Scroll 的高资源消耗问题。

4. 为什么 Search After 需要 "Tie-breaker"?

这是使用 Search After 最容易踩坑的地方。
假设你按 timestamp 排序。如果有多条日志的时间戳完全一样:

  1. 第一页最后一条数据时间是 12:00:00
  2. 你告诉 ES:“给我 12:00:00 之后的数据”。
  3. ES 可能会困惑,因为还有其他数据也是 12:00:00,它不知道哪些已经在上一页显示过了。

解决方案
必须在排序中加入一个全局唯一的字段(通常是 _id)。
排序规则变成:sort: [{ "timestamp": "desc" }, { "_id": "asc" }]
这样生成的 sort values 类似于 [1689000000, "abc-123"],这就具有了唯一性,ES 就能精准定位。


5. 总结与最佳实践

  • 不要再使用 from + size 翻页超过 10,000 条数据。
  • 如果是旧版本 ES 且做离线数据迁移,可以用 Scroll
  • 如果是在线业务(如无限滚动列表),必须使用 Search After
  • 如果是新版本 ES (7.10+)全量导出,请使用 Search After + PIT (Point In Time)。这是目前最完善的解决方案,它结合了 Scroll 的数据一致性优势和 Search After 的轻量级优势。
右滑查看面试常问