复制数据:Copy Slice

更新时间:
复制 MD 格式

Copy Slice 用于在同一 Collection 中,将源 Slice 的可复制文档复制到新的或空的目标 Slice,保留源 Slice 及其数据。目标 Slice 会按自身 Backing 的分片配置重新建立索引,因此可以让同一份数据使用不同的主分片数或路由分区,以适应数据量或查询负载变化。应用仍通过 Collection 和 Slice 访问,分片调整对调用方透明。它通过完整复制准备一份数据拷贝,不是时间点快照、备份或原子切流工具。

Copy 需要逐文档重新写入,复制耗时和读写开销随数据量增长。

调整目标分片配置(可选)

无需调整分片配置时,可以直接启动 Copy。如果需要让目标 Slice 使用不同的主分片数或路由分区,请先通过更新 Collection 设置后续 Backing 的参数,再预创建 Backing。预创建多个 Backing 后,系统会把新 Slice 的分配策略切换为 random;如果目标必须使用刚创建的 Backing,请在预创建后将策略改回 last,再注册目标 Slice。注册目标 Slice 后,先确认其 backing_index 使用了新 Backing,再启动 Copy;Copy API 不能直接指定目标 Backing。

启动 Copy

先确认源数据已经可搜索,目标使用新 Slice 或没有可搜索文档的 Slice;源文档必须符合本文 Copy 数据语义中的 _source 和 Mapping 要求。Copy 会读取源数据并写入目标,持续写入的增量不会自动同步,切换流量前需要另行处理。

POST /_slice_collection/{collection}/slices/{source}/_copy/{target}

查询参数:

参数

默认值

说明

wait_for_completion

true

是否等待 Copy 进入完成状态。设置为 false 时异步返回。

timeout

30s

当前 HTTP 请求的等待预算。超时不会停止后台 Copy。

请求体参数均为可选:

参数

默认值

取值范围或说明

workers

执行节点处理器数的一半,向上取整,并限制在 1~64

并行复制的工作任务数;不支持在运行中动态调整。

batch_size

5000

每批复制的文档数上限,取值范围 1~10000。内存压力触发熔断时,服务端会自动将批次减半后重试,最低为 1;因此实际批次可能小于设置值,持续降到 1 仍失败时 Copy 转为 FAILED。

requests_per_second

-1

整个 Copy 的目标文档处理速率,单位为文档/秒,由各 worker 分摊;按批次节流,并非 HTTP 请求数/秒。-1 表示不限速。

以下示例从 1 个 worker、每批 500 条、总速率 500 条/秒开始。这些是便于控制初始负载的示例值,不是默认值或吞吐保证;应根据文档大小、源查询开销和目标写入负载评估后调整。

POST /_slice_collection/knowledge-chunks/slices/tenant-a/_copy/tenant-a-copy?wait_for_completion=false
{
  "workers": 1,
  "batch_size": 500,
  "requests_per_second": 500
}

异步请求返回 HTTP 202 Accepted。请保存响应中的 copy_id,并优先使用服务端返回的 status_url 和 cancel_url;响应头 Location 也提供状态查询地址。响应示例:

{
  "copy_id": "opaque-copy-id",
  "completed": false,
  "timed_out": false,
  "state": "RUNNING",
  "source": "tenant-a",
  "target": "tenant-a-copy",
  "progress": { "total": 0, "created": 0, "version_conflicts": 0 },
  "status_url": "/_slice_collection/knowledge-chunks/_copy/opaque-copy-id",
  "cancel_url": "/_slice_collection/knowledge-chunks/_copy/opaque-copy-id/_cancel"
}

workers 仅在执行并行度已确定且大于 0 时返回,调用方不能假设刚提交的响应一定包含该字段。失败时还会返回 error,用于说明失败原因。

copy_id 是不透明标识,可能包含冒号等 URL 保留字符。自行拼接状态查询地址时需要进行 URL 编码,建议直接使用响应返回的 status_url 和 cancel_url。

运行中的响应包含 progress 对象;只有 state=SUCCEEDED 时使用 result。FAILED 和 CANCELLED 仍使用 progress,表示结束前已完成的工作。三种结束状态均包含 completed=true 和耗时 took(毫秒)。version_conflicts 位于相应的 progress 或 result 中。

使用默认的 wait_for_completion=true 时,如果 Copy 在 timeout 内进入终态,接口返回 HTTP 200;等待超时则返回 HTTP 202 和 timed_out=true,后台 Copy 继续运行。客户端断开也不会自动取消 Copy。

重要

HTTP 200 只表示 Copy 已进入终态,也可能是 FAILED 或 CANCELLED。

查询 Copy 状态

GET /_slice_collection/knowledge-chunks/_copy/<copy_id>

状态

含义

RUNNING

正在复制或等待自动恢复。

CANCELLING

已接受取消请求,正在停止。

SUCCEEDED

Copy 成功完成。

FAILED

Copy 无法继续,响应包含 error。

CANCELLED

Copy 已取消,目标 Slice 和已复制数据保留。

状态查询成功时固定返回 HTTP 200,包括 state=FAILED。调用方必须检查 state 和 error,不能只看 HTTP 状态码。

按有间隔的方式查询状态,进入终态后停止轮询。SUCCEEDED 表示复制任务完成,不等于目标数据已全部可搜索;验证或切流前还需等待后台刷新,再检查目标查询结果;对冷查询延迟敏感时,提前预热即将访问的 Slice。Copy 长时间处于 RUNNING 且进度缓慢时,可能是服务端因内存压力自动调小了批次,属于自我保护行为;先继续按间隔查询,不要立即取消并重试。

调整状态保留时长(可选)

完成状态默认至少保留 1d,之后查询可能返回 HTTP 404。调用方不应把 Copy 状态接口作为长期审计存储。保留时长由动态集群设置 apack.slice_collection.copy.reservation_retention 控制,最小值为 1h:

PUT /_cluster/settings
{
  "persistent": {
    "apack.slice_collection.copy.reservation_retention": "1d"
  }
}

取消 Copy

POST /_slice_collection/knowledge-chunks/_copy/<copy_id>/_cancel

取消操作不会删除目标 Slice 或已经复制的文档。接受异步取消时,接口返回 HTTP 202 和 state=CANCELLING;继续轮询,直到 completed=true,通常会看到 state=CANCELLED。如果 Copy 在取消生效前已成功或失败,会返回对应的结束状态。结束后 cancel_url 消失;重复取消已结束的 Copy 返回当前状态和 HTTP 200。

Copy 数据语义

Copy 创建一份新的数据副本,源 Slice 的位置保持不变。以下说明目标如何分配,以及复制时如何处理文档。

  • 源 Slice 和目标 Slice 必须属于同一个 Collection,且名称不能相同。

  • 启动时,目标 Slice 必须没有可搜索文档;已有可搜索文档时返回 target_not_empty。该检查不会锁定目标,后续并发写入仍可能产生同 ID 冲突。

  • 目标 Slice 不存在时,按 Collection 当前的普通 Slice 分配规则自动注册,即使 auto_create_slice=false;目标已存在时,沿用其 Backing 和分片位置。后续准入失败不会自动删除刚注册的目标 Slice。

  • Copy 可以跨 Backing 或分片复制,支持源、目标采用不同的分片数和路由分区配置,文档按目标的配置重新建立索引。

  • Copy API 不提供指定目标 Backing 或分片的参数,也不保证新目标与源位于不同分片。若为后续 Backing 调整了分片数或路由分区配置,只有之后新建的 Backing 才会使用新配置;Copy 不会修改已有目标的分片布局,见后续生效设置。

  • Copy 使用 create-only 写入,不覆盖目标 Slice 中已有的同 _id 文档;冲突计入 version_conflicts,其他文档继续复制。Copy 完成后应检查该字段,并根据业务需要处理同 ID 数据。

  • Copy 保留文档内容,包括 routing_field 指向的字段。例如,routing_field=cluster_id 时,将 cluster-a 复制到 cluster-b 后,目标文档中的 cluster_id 仍为 cluster-a。后续通过 Index 或 Bulk 向目标写回文档时,应显式指定 _slice=cluster-b,并把文档的 cluster_id 改为 cluster-b。原样写回且省略 _slice 或 routing 会按字段值写入源 Slice;显式指定目标但保留源字段值,默认校验会返回 HTTP 400。不要通过关闭校验规避,应在应用切流前调整写入逻辑。

  • 向量簇模式下,Copy 只复制文档,不复制 Slice 的中心向量;目标自动注册时没有中心向量,因此不会参与自动选片。目标要参与自动选片时,应单独注册中心向量,也可以先注册带中心向量的空目标,再执行 Copy。

  • Copy 期间源 Slice 和目标 Slice 都可以读写,因此结果不是源 Slice 的原子时间点快照。

  • 源 Slice 必须保留能够重建文档的完整 _source。关闭 _source、使用 synthetic _source、配置非空 _source.includes,或通过 _source.excludes 排除了仍用于索引、排序、copy_to 或多字段的内容时,Copy 会被拒绝。仅排除可由索引安全恢复的字段可能可用,最终以服务端校验结果为准。

  • 源 Slice 的 Mapping 包含 semantic_text 等推理字段时,当前不支持 Copy。

  • default/final ingest pipeline 不会在 Copy 时重复执行。

  • 文档会按目标当前 Mapping 重新应用,例如新增 multi-field 会在目标中生成。Copy 期间应避免会影响结果解释的 Mapping 变更。

常见启动错误:

HTTP

error.type

处理建议

400

source_disabled

使用保留了完整可复制内容的 _source。

400

source_representation_unsupported

检查 synthetic _source、_source 过滤和推理字段。

409

target_not_empty

目标 Slice 已经可以搜索到数据。确认目标名称,通常应改用新的目标 Slice。

409

target_lifecycle_conflict

目标 Slice 正被其他 Copy 或删除操作占用。如响应包含 status_url,先查看现有 Copy。

如果需要在 Copy 完成后切换业务流量,请在应用层检查 Copy 状态和结果,再通过业务配置切换到目标 Slice。

有关 Copy 与 Branch 的选型,参阅可写数据分支:Branch Slice(Beta)。