预热 Slice 缓存

更新时间:
复制 MD 格式

_warm_slice 将指定 Slice 的向量、文本索引,以及排序、聚合和返回字段所需的数据预取到查询节点的本地共享缓存,减少随后查询因缓存未命中而等待对象存储读取的时间。它不改变查询结果,也不保证缓存驻留时长。

预热是可选的性能优化,未预热时查询会按需加载数据。需要预热时,先等待后台自动刷新使数据可搜索。 不要为预热手动调用 _refresh;预热不会触发刷新,也不包含之后才变为可搜索的新数据。生产环境应提前预热即将使用的冷 Slice,控制并发;同一批数据预热完成后直接查询,无需在每次查询前重复预热。

发起异步预热

默认以异步方式提交预热任务:

POST /knowledge-chunks/_warm_slice?_slice=tenant-a

请求返回 HTTP 200,响应体中的 status 为 ACCEPTED,并包含本次预热任务的 ID:

{
  "status": "ACCEPTED",
  "message": "cache warm hint accepted",
  "task": "<nodeId>:<taskId>"
}

使用以下接口查询正在运行的任务:

GET /_tasks/<nodeId>:<taskId>

默认情况下任务完成后不保留结果。如果需要在完成后继续查询任务结果,请在提交时设置 store_result=true:

POST /knowledge-chunks/_warm_slice?_slice=tenant-a&store_result=true

ACCEPTED 仅表示任务已提交,不表示目标 Slice 存在或预热成功。 需要确认结果时,使用 store_result=true,再通过 Tasks API 依次检查:

  1. completed=true:任务已结束;为 false 时,间隔一段时间继续查询。

  2. 顶层不存在 error:任务未以错误结束。不存在的 Slice、暂不支持预热的 Active Branch 等情况,可能在提交后才报告错误。

  3. response._shards.failed=0:没有分片失败。若 response._shards.total=0,按下文的同步结果判断进一步核对。

优先使用应用已知的目标 Slice,不要为了预热而遍历全部 Slice。

等待预热完成

需要直接获取预热统计时,可以同步等待:

POST /knowledge-chunks/_warm_slice?_slice=tenant-a&wait_for_completion=true&timeout=60s

查询参数:

参数

是否必填

默认值

说明

slice 或 _slice

是

无

要预热的一个 Slice。两个参数同时存在时,值必须相同,否则返回 HTTP 400。

wait_for_completion

否

false

是否等待预热结果返回。

store_result

否

false

是否在任务完成后保留结果,供 Tasks API 查询。

timeout

否

无

等待分片响应的最长时间,例如 60s。

同步模式对不存在的 Slice 返回 HTTP 404。请求成功后检查顶层 _shards.failed=0;如果 _shards.total=0,不能据此判断查询节点已经就绪。预期已有可搜索数据时,应先确认查询分片可用,并用实际查询核对数据可见性,再按需重试预热。空数据 Slice 不应仅因这一结果判为失败。

同步响应还包含以下统计字段:

字段

说明

segments_matched

当前可搜索数据中命中该 Slice 的 Segment 数。

docs_read

规划预热范围时读取的文档数。

ranges_requested

请求预热的数据范围数。

ranges_warmed

成功预热的数据范围数。

ranges_skipped

因文件已被合并或删除等原因跳过的数据范围数。

bytes_requested

请求预热的字节数。

使用时请注意:

  • 每次请求只能明确指定一个 Collection 和一个 Slice。缺失的 Slice 不会被自动注册,也不能使用 _all。

  • 同一查询分片副本和 Slice 的并发预热请求会合并,无需重复提交。

  • 预热只处理请求发起时已经可搜索的数据。之后变为可搜索的新数据不包含在本次预热结果中。

  • ranges_skipped 大于 0 不一定表示预热失败;文件在预热期间被合并或删除时,对应范围会被跳过。

  • 预热会消耗对象存储读取带宽和查询节点资源。生产环境建议使用默认异步方式,并控制同时预热的 Slice 数量。

  • 预热队列已满时,服务端可能拒绝新请求。客户端应采用有上限的退避重试,不要立即并发重试全部 Slice。

查询与预热亲和性

各查询节点的本地缓存彼此独立,同一分片的不同可搜索副本如果位于不同节点,不能直接共享已缓存的数据。因此系统默认开启查询与预热亲和性:在分片路由保持稳定时,预热和后续查询会优先访问 同一个可搜索副本,从而复用该副本所在查询节点的本地缓存,减少从对象存储重复读取数据以及多个副本重复缓存相同数据。

例如,打开一个低频知识库前先预热,完成后发起查询。以下同步写法用于展示调用顺序,生产环境建议按上文提前异步预热,避免让用户的每次查询都等待预热:

POST /knowledge-chunks/_warm_slice?_slice=tenant-a&wait_for_completion=true&timeout=60s

按上文检查预热结果后,再执行查询:

GET /knowledge-chunks/_search?_slice=tenant-a

亲和性只影响优先访问的副本,不改变查询结果。适用范围包括:

  • GET、MGet 和 Explain;

  • Search、Count、Search Template、Search Shards、Async Search 和 Multi Search 中的 Collection 子请求;

  • 单 Slice、多 Slice 和 _slice=_all 查询;

  • Update By Query 和 Delete By Query;

  • _warm_slice。

不适用于 Reindex 的源端读取和 Validate Query。Copy Slice 使用 Reindex 读取源数据,同样不能保证复用刚预热的那个副本的缓存。

开启亲和性时(默认),调用方无需设置 preference,请求中传入的 preference 会被亲和性规则覆盖。 如果业务需要用 preference 控制节点选择,例如通过 _local 优先访问本地节点或通过 _only_nodes 仅访问指定节点,需要由集群管理员关闭亲和性。

该设置对所有 Collection 生效,不能仅为一个 Collection 修改。关闭后,未携带 preference 的预热会覆盖目标分片的全部可搜索副本,可能增加对象存储读取量和本地缓存占用。确认这一影响后再调整:

PUT /_cluster/settings
{
  "persistent": {
    "apack.slice_collection.query_warm_affinity.enabled": false
  }
}

该设置动态生效,无需重建 Collection。关闭后,请求中的 preference 恢复生效;查询未传入该参数时,使用原有的副本选择方式。

无论是否开启,副本迁移、不可用或请求重试时,实际访问的副本都可能发生变化。亲和性不保证请求永久绑定到某个节点。