ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

如何用 ExportSnapshot 与 RestoreExternalSnapshot 跨桶导出和恢复 Milvus 快照

如何用 ExportSnapshot 与 RestoreExternalSnapshot 跨桶导出和恢复 Milvus 快照 如何用 ExportSnapshot 与 RestoreExternalSnapshot 跨桶导出和恢复 Milvus 快照【免费下载链接】milvusMilvus is a high-performance, cloud-native vector database built for scalable vector ANN search项目地址: https://gitcode.com/GitHub_Trending/mi/milvus默认情况下Milvus 快照只归属于一个集群和对象存储桶RestoreSnapshot恢复的是目标集群元数据里已经存在的快照。当你想把某个集合的数据备份到另一个桶、或者让另一个集群从对象存储的元数据 URI 直接恢复时需要用ExportSnapshot把快照打成一个自包含的 bundle 写到目标桶再在目标侧调用RestoreExternalSnapshot恢复。两个接口都是异步任务提交后返回job_id通过状态轮询接口确认完成。本文的操作路径基于仓库中的设计文档 外部快照导出与恢复、Go SDK 实现 snapshot.go 与端到端测试用例 snapshot_test.go。开始前的准备先创建一个普通快照。ExportSnapshot的输入是本地已存在的快照所以先用CreateSnapshot在源集群创建快照并命名导出、恢复都基于这个快照名和集合名进行。确认凭证模型。跨桶复制必须满足一个前提存在一个对象存储 provider 端的复制请求其凭证既能读源对象、又能写目标对象。API 不引入独立的凭证抽象只有两层解析方式Layer 1实例凭证 桶策略。请求中external_spec留空时使用 Milvus 实例的对象存储凭证需要为该 principal 授予缺失桶的权限导出时是外桶写权限恢复时是外桶读权限。Layer 2请求中的external_spec.extfs。可携带与存储配置兼容的字段provider、region、endpoint、TLS 模式、use_iam、AK/SK或 GCP 服务账号 JSONcredential_json。显式的请求凭证会覆盖实例凭证且use_iamtrue、原始 AK/SK、credential_json三者互斥。通用的role_arn、SAS 作为凭证模式、匿名认证都会被拒绝。一个安全注意点恢复链路会把external_spec从 Proxy 一路透传到 DataCoord、WAL、任务状态和 DataNode其中的原始密钥会被持久化。设计文档把这一点标为运维红线建议优先使用 Layer 1 或use_iamtrue这类环境身份字段避免在请求里传明文密钥日志与错误信息中的 spec 会自动脱敏。权限。ExportSnapshot、GetExportSnapshotState和RestoreExternalSnapshot都是 Global RBAC 操作导出的提交和状态查询使用PrivilegeExportSnapshot权限。db_name仍保留在请求中用于数据库路由与命名空间上下文但不是 RBAC 检查对象。跨桶复制的边界。跨桶复制是 provider 侧复制能力没有流式兜底不同 provider、不同 endpoint包括相互独立的 MinIO/S3 兼容服务之间无法用一次服务端复制请求完成Milvus 会在调度前直接拒绝而不是先跑任务再失败。第一步创建源快照在源集群对目标集合创建快照。Go SDK 中err : client.CreateSnapshot( ctx, milvusclient.NewCreateSnapshotOption(snapshot_20260608, source_collection), )用ListSnapshots确认快照名已出现在集合的快照列表中即可进入导出步骤。如果后续走的是referenced 快照恢复路径见文末说明此时用DescribeSnapshot拿到的s3_location就是可直接恢复的元数据 URI导出 bundle 的路径则由下面几步完成。第二步用 ExportSnapshot 导出到目标桶exportJobID, err : client.ExportSnapshot( ctx, milvusclient.NewExportSnapshotOption( snapshot_20260608, // 第一步创建的快照名 source_collection, // 源集合名 s3://foreign-bucket/export-root, // 导出目标根路径 ).WithExternalSpec({extfs:{cloud_provider:aws,region:us-west-2,use_iam:true}}), )以上示例值取自设计文档替换为你自己的快照名、集合名和导出根。提交后接口立即返回exportJobID任务在后台执行。几个执行语义需要在提交前理解目标根路径。每个被接受的任务都会把自包含 bundle 写到target_s3_path/exports/export-id下其中export-id是系统生成的随机命名空间两个集群可以请求同一个目标根而不会互相覆盖元数据或对象。目标可以是配置的源桶也可以是另一个桶指向源桶内对象 key 的目标同样被接受。同桶覆盖保护。如果目标路径属于源桶DataCoord 会在复制开始前构建完整的源对象集合只要生成的目标元数据、segment manifest 或数据对象 key 与源快照对象有交集任务直接失败。不同桶中 key 相同不算冲突仍会正常复制。external collection 被拒绝。外部集合的 lake fragment 不在快照文件集内ExportSnapshot会在枚举和复制之前拒绝这类集合。复制方式。对象由 provider 侧完成复制不经过 Milvus 节点中转单次导出任务的总生命周期由dataCoord.snapshot.exportJobTimeout约束。external_spec的字段规则以设计文档第 4 节为准如果 metadata URI 中已编码了 endpoint/provider/region/TLS 信息与之冲突的external_spec值会被拒绝。第三步轮询导出状态拿到 metadata URIexportInfo, err : client.GetExportSnapshotState( ctx, milvusclient.NewGetExportSnapshotStateOption(exportJobID), ) metadataURI : exportInfo.GetSnapshotMetadataUri() // 仅 Completed 后可用按设计文档的测试用例 snapshot_test.go 中的做法用ExportSnapshotCompleted作为成功条件、ExportSnapshotFailed作为失败条件做轮询用例中失败时读取info.GetReason()获取原因。任务完成后的验证点状态为CompletedsnapshotMetadataUri非空且与DescribeSnapshot返回的s3_location不同后者指向源快照前者指向导出 bundletotalBytes为正数等于唯一复制的数据对象加上生成的 segment manifest 与最终元数据的字节数只有Completed状态才暴露 metadata URI 和totalBytes内部Publishing状态在公开 API 上映射为Executing且进度 99。对远程对象存储DescribeSnapshot.s3_location与完成的导出元数据位置都是不带凭证的完整 URI标准 S3 兼容 provider 形如https://endpoint/bucket/object-key原生 GCS 为gs://Azure 为azure://account-endpoint/container/object-key。endpoint 保留在 URI 里是为了让另一个集群恢复时仍能定位 provider。第四步用 RestoreExternalSnapshot 恢复在目标集群提交恢复请求输入是恢复后的集合名和上一步拿到的 metadata URIjobID, err : client.RestoreExternalSnapshot( ctx, milvusclient.NewRestoreExternalSnapshotOption( restored_collection, // 恢复后创建的集合名 s3://foreign-bucket/export-root/exports/export-id/snapshots/100/metadata/1.json, ).WithExternalSpec({extfs:{cloud_provider:aws,region:us-west-2,use_iam:true}}), )其中export-id是导出时生成的命名空间snapshots/100/metadata/1.json是 bundle 内部的真实路径示例实际操作中直接粘贴第三步GetExportSnapshotState返回的 metadata URI 即可不要手工拼路径。URI 必须是带 scheme 和 host 的完整地址只给对象 key 会被拒绝。然后轮询恢复状态info, err : client.GetRestoreSnapshotState( ctx, milvusclient.NewGetRestoreSnapshotStateOption(jobID), )恢复完成的验证方式与测试用例一致状态达到RestoreSnapshotCompleted后确认目标集合已存在HasCollection加载集合LoadCollection并等待完成再用强一致性级别对恢复后的集合查询行数与导出前源集合的行数核对。状态为RestoreSnapshotFailed时读取reason字段定位原因。可选手动搬迁整个 bundle 后再恢复自包含 bundle 的目录布局固定为root/snapshots/{collectionID}/metadata/{snapshotID}.json root/snapshots/{collectionID}/manifests/... root/files/...ExportSnapshot写入的是export-root/exports/export-id/snapshots/.../metadata/....json加export-root/exports/export-id/files/...。如果你把整个 bundle 原样复制到新的根前缀例如restored/x/snapshots/...与restored/x/files/...恢复时只需把新的 metadata URI 传给RestoreExternalSnapshotMilvus 会从导出时元数据里取oldRoot、从恢复请求 URI 取newRoot自动把自包含路径从oldRootrebase 到newRoot不需要额外的 root 重写参数。搬迁有两个硬性约束bundle 内部布局不能变files/不能改名、层级不能拆且 metadata URI 必须保留snapshots/.../metadata/...锚点。如果搬成restored/x/meta.json这类没有snapshots锚点的布局Milvus 无法推断根是restored还是restored/x请求会失败这是设计上的 fail-closed 行为不是可以通过参数绕过的错误。REST 调用方式REST 路由使用 camelCase 字段external_spec对应 JSON 里的externalSpec# 提交导出字段值需替换为你的实例地址、令牌与实际名称 curl -X POST $MILVUS_ADDR/v2/vectordb/jobs/snapshot/export \ -H Content-Type: application/json \ -H Authorization: Bearer $TOKEN \ -d { dbName: default, collectionName: source_collection, snapshotName: snapshot_20260608, targetS3Path: s3://foreign-bucket/export-root, externalSpec: {\extfs\:{\cloud_provider\:\aws\,\region\:\us-west-2\,\use_iam\:\true\}} }# 查询导出状态 curl -X POST $MILVUS_ADDR/v2/vectordb/jobs/snapshot/export/describe \ -H Content-Type: application/json \ -H Authorization: Bearer $TOKEN \ -d {jobId:12345}# 提交外部恢复 curl -X POST $MILVUS_ADDR/v2/vectordb/jobs/snapshot/restore_external \ -H Content-Type: application/json \ -H Authorization: Bearer $TOKEN \ -d { dbName: default, targetCollectionName: restored_collection, snapshotMetadataURI: s3://foreign-bucket/export-root/exports/export-id/snapshots/100/metadata/1.json, externalSpec: {\extfs\:{\cloud_provider\:\aws\,\region\:\us-west-2\,\use_iam\:\true\}} }# 查询恢复状态 curl -X POST $MILVUS_ADDR/v2/vectordb/jobs/snapshot/describe \ -H Content-Type: application/json \ -H Authorization: Bearer $TOKEN \ -d {jobId:12345}$MILVUS_ADDR与$TOKEN替换为你自己的实例地址和认证令牌export-id以导出完成后状态接口返回的 metadata URI 为准。REST 测试用例 test_snapshot_operations.py 展示了完整的调用序列提交导出返回jobId轮询到ExportSnapshotCompleted后取snapshotMetadataURI和totalBytes再用该 URI 提交restore_external并轮询到RestoreSnapshotCompleted。相关配置项以下配置位于 milvus.yaml 的dataCoord.snapshot段915–922 行附近按默认值即可执行本文流程仅在大数据量或高并发导出时需要调整配置项默认值作用exportCopyConcurrency16单个导出任务的 provider 端对象复制并发上限非法或非正值回落到 16exportMaxConcurrentJobs1DataCoord 并发执行的导出任务数exportJobTimeout4320012 小时秒被接受的导出任务总生命周期含排队等待exportJobRetention108003 小时秒终态任务在 pin 清理后保留终态信息的时长crossBucketEndpointAllowlist空使用自定义对象存储 endpoint 做服务端跨桶复制时的 endpoint 白名单由cloud_provider和region推导出的标准云 endpoint 不需要配置限制与已知行为不支持跨 provider、跨 endpoint 复制也没有流式兜底provider、endpoint、region 或凭证探测显示无法表达为单次 provider 端复制请求时请求在调度前被拒绝。referenced 快照恢复要求源文件保持可读。如果直接用DescribeSnapshot.s3_location恢复referenced 布局元数据仍指向原始 segment/index 文件恢复期间源快照和被引用文件必须可读源快照被删除且 GC 清掉了引用文件时恢复会失败。自包含 bundle 没有这个外部依赖这也是备份场景推荐走ExportSnapshot的原因。失败的导出可能留下无引用的孤儿对象。Milvus 不会自动删除它们因为对象路径可能已被旧的已发布 bundle 共享后续重试可以安全地覆盖不可变的快照对象。external collection 暂不支持导出详见前文说明。凭证模式互斥use_iamtrue、原始 AK/SK、credential_json只能选一种请求级的ssl_ca_cert会被接受但忽略自定义 CA 信任必须来自 Milvus 实例的存储配置。【免费下载链接】milvusMilvus is a high-performance, cloud-native vector database built for scalable vector ANN search项目地址: https://gitcode.com/GitHub_Trending/mi/milvus创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进