스냅샷 (Snapshots)

스냅샷 (Snapshots)

사용 가능 버전: v0.8.4부터

스냅샷(Snapshot)은 특정 노드의 특정 컬렉션에 들어 있는 데이터와 설정을 특정 시점에 그대로 담아 둔 tar 아카이브 파일이에요. 분산 구성에서 여러 노드로 클러스터를 운영 중이라면, 컬렉션 하나를 다룰 때도 노드마다 스냅샷을 각각 만들어 줘야 해요.

이 기능은 데이터를 보관(아카이브)하거나 기존 배포 구성을 쉽게 복제할 때 쓸 수 있어요. 재해 복구 목적이라면 Qdrant Cloud 사용자는 물리 디스크 수준의 복사본인 Backups을 선호할 거예요.

컬렉션 수준 스냅샷에는 해당 컬렉션의 데이터만 들어 있어요. 컬렉션 설정과 모든 포인트·페이로드가 포함되죠. 컬렉션 별칭(alias)은 포함되지 않으므로 별도로 마이그레이션하거나 복구해야 해요.

스냅샷 사용법을 처음부터 단계별로 보고 싶다면 튜토리얼을 참고하세요.

스냅샷 만들기

기존 컬렉션의 스냅샷을 새로 만드는 방법이에요.

 POST /collections/{collection_name}/snapshots
 from qdrant_client import QdrantClient
 client = QdrantClient(url="http://localhost:6333")
 client.create_snapshot(collection_name="{collection_name}")
 import { QdrantClient } from "@qdrant/js-client-rest";
 const client = new QdrantClient({ host: "localhost", port: 6333 });
 client.createSnapshot("{collection_name}");
 use qdrant_client::Qdrant;
 let client = Qdrant::from_url("http://localhost:6334").build()?;
 client.create_snapshot("{collection_name}").await?;
 import io.qdrant.client.QdrantClient;
 import io.qdrant.client.QdrantGrpcClient;
 QdrantClient client = new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
 client.createSnapshotAsync("{collection_name}").get();
 using Qdrant.Client;
 var client = new QdrantClient("localhost", 6334);
 await client.CreateSnapshotAsync("{collection_name}");
 import (
     "context"
     "github.com/qdrant/go-client/qdrant"
 )
 client, err := qdrant.NewClient(&qdrant.Config{
     Host: "localhost",
     Port: 6334,
 })
 client.CreateSnapshot(context.Background(), "{collection_name}")

이 작업은 동기적으로 실행되며, snapshot_pathtar 아카이브 파일이 생성돼요.

스냅샷 삭제

사용 가능 버전: v1.0.0부터

 DELETE /collections/{collection_name}/snapshots/{snapshot_name}
 from qdrant_client import QdrantClient
 client = QdrantClient(url="http://localhost:6333")
 client.delete_snapshot(collection_name="{collection_name}", snapshot_name="{snapshot_name}")
 import { QdrantClient } from "@qdrant/js-client-rest";
 const client = new QdrantClient({ host: "localhost", port: 6333 });
 client.deleteSnapshot("{collection_name}", "{snapshot_name}");
 use qdrant_client::qdrant::DeleteSnapshotRequestBuilder;
 use qdrant_client::Qdrant;
 let client = Qdrant::from_url("http://localhost:6334").build()?;
 client.delete_snapshot(DeleteSnapshotRequestBuilder::new("{collection_name}", "{snapshot_name}")).await?;
 import io.qdrant.client.QdrantClient;
 import io.qdrant.client.QdrantGrpcClient;
 QdrantClient client = new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
 client.deleteSnapshotAsync("{collection_name}", "{snapshot_name}").get();
 using Qdrant.Client;
 var client = new QdrantClient("localhost", 6334);
 await client.DeleteSnapshotAsync(collectionName: "{collection_name}", snapshotName: "{snapshot_name}");
 import (
     "context"
     "github.com/qdrant/go-client/qdrant"
 )
 client, err := qdrant.NewClient(&qdrant.Config{
     Host: "localhost",
     Port: 6334,
 })
 client.DeleteSnapshot(context.Background(), "{collection_name}", "{snapshot_name}")

스냅샷 목록 조회

컬렉션에 대한 스냅샷 목록을 가져와요.

 GET /collections/{collection_name}/snapshots
 from qdrant_client import QdrantClient
 client = QdrantClient(url="http://localhost:6333")
 client.list_snapshots(collection_name="{collection_name}")
 import { QdrantClient } from "@qdrant/js-client-rest";
 const client = new QdrantClient({ host: "localhost", port: 6333 });
 client.listSnapshots("{collection_name}");
 use qdrant_client::Qdrant;
 let client = Qdrant::from_url("http://localhost:6334").build()?;
 client.list_snapshots("{collection_name}").await?;
 import io.qdrant.client.QdrantClient;
 import io.qdrant.client.QdrantGrpcClient;
 QdrantClient client = new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
 client.listSnapshotAsync("{collection_name}").get();
 using Qdrant.Client;
 var client = new QdrantClient("localhost", 6334);
 await client.ListSnapshotsAsync("{collection_name}");
 import (
     "context"
     "github.com/qdrant/go-client/qdrant"
 )
 client, err := qdrant.NewClient(&qdrant.Config{
     Host: "localhost",
     Port: 6334,
 })
 client.ListSnapshots(context.Background(), "{collection_name}")

스냅샷 다운로드

컬렉션에서 지정한 스냅샷을 파일로 내려받아요.

 GET /collections/{collection_name}/snapshots/{snapshot_name}
 curl 'http://{qdrant-url}:6333/collections/{collection_name}/snapshots/snapshot-2022-10-10.snapshot' \
 -H 'api-key: ********' \
 --output 'filename.snapshot'
 curl 'http://{qdrant-url}:6333/collections/{collection_name}/snapshots/snapshot-2022-10-10.snapshot' \
 -H 'api-key: ********' \
 --output 'filename.snapshot'

스냅샷 복구

스냅샷은 세 가지 방식으로 복구할 수 있어요.

  1. URL 또는 로컬 파일에서 복구 — 원격 서버에 있거나 이미 노드에 저장된 스냅샷 파일을 복구할 때 유용해요.
  2. 업로드한 파일에서 복구 — 새 클러스터로 데이터를 마이그레이션할 때 유용해요.
  3. 시작 시 복구 — 자체 호스팅 단일 노드 Qdrant 인스턴스를 실행할 때 유용해요.

어떤 방법을 쓰든 Qdrant는 스냅샷에서 샤드 데이터를 추출해 클러스터에 샤드를 제대로 등록해요. 복구한 샤드의 다른 활성 복제본이 이미 클러스터에 있다면, 기본적으로 Qdrant가 새로 복구된 노드로 복제해 데이터 일관성을 유지해요.

URL 또는 로컬 파일에서 복구

사용 가능 버전: v0.11.3부터

이 방식은 스냅샷 파일을 URL로 내려받을 수 있거나, 노드의 로컬 파일로 존재해야 해요(예: 이전에 이 노드에서 스냅샷을 만든 경우). 스냅샷 파일을 업로드해야 한다면 다음 섹션을 참고하세요.

URL 또는 로컬 파일에서 복구할 때는 스냅샷 복구 엔드포인트를 사용해요. 이 엔드포인트는 https://example.com 같은 URL이나 file:///tmp/snapshot-2022-10-10.snapshot 같은 파일 URI를 받아요. 대상 컬렉션이 존재하지 않으면 새로 만들어져요.

 PUT /collections/{collection_name}/snapshots/recover
 {
   "location": "http://qdrant-node-1:6333/collections/{collection_name}/snapshots/snapshot-2022-10-10.snapshot"
 }
 from qdrant_client import QdrantClient
 client = QdrantClient(url="http://qdrant-node-2:6333")
 client.recover_snapshot(
     "{collection_name}",
     "http://qdrant-node-1:6333/collections/collection_name/snapshots/snapshot-2022-10-10.snapshot",
 )
 import { QdrantClient } from "@qdrant/js-client-rest";
 const client = new QdrantClient({ host: "localhost", port: 6333 });
 client.recoverSnapshot("{collection_name}", {
     location: "http://qdrant-node-1:6333/collections/{collection_name}/snapshots/snapshot-2022-10-10.snapshot",
 });

업로드한 파일에서 복구

스냅샷 파일을 파일로 업로드해 복구할 수도 있어요. 업로드한 스냅샷 복구 엔드포인트가 요청 본문에 스냅샷 원본 데이터를 받아요. 대상 컬렉션이 존재하지 않으면 새로 만들어져요.

 curl -X POST 'http://{qdrant-url}:6333/collections/{collection_name}/snapshots/upload?priority=snapshot' \
 -H 'api-key: ********' \
 -H 'Content-Type:multipart/form-data' \
 -F 'snapshot=@/path/to/snapshot-2022-10-10.snapshot'

이 방식은 주로 한 클러스터에서 다른 클러스터로 데이터를 마이그레이션할 때 쓰여요. 그 용도라면 priority를 snapshot으로 설정하는 걸 권장해요.

시작 시 복구

단일 노드 배포라면 시작 시 컬렉션을 복구할 수 있고, 복구된 컬렉션은 바로 사용 가능해요. 스냅샷 복구는 시작 시점에 Qdrant CLI의 --snapshot 인자로 수행해요. 이 인자는 <snapshot_file_path>:<target_collection_name> 형태의 쌍 목록을 받아요.

예를 들어:

 ./qdrant --snapshot /snapshots/test-collection-archive.snapshot:test-collection --snapshot /snapshots/test-collection-archive.snapshot:test-copy-collection

대상 컬렉션은 반드시 존재하지 않아야 해요. 존재하면 프로그램이 오류와 함께 종료돼요.

대신 기존 컬렉션을 덮어쓰고 싶다면 --force_snapshot 플래그를 주의해서 사용하세요.

스냅샷 우선순위

비어 있지 않은 노드에 스냅샷을 복구하면 스냅샷 데이터와 기존 데이터 사이에 충돌이 생길 수 있어요. priority 설정이 이런 충돌을 Qdrant가 어떻게 처리할지 결정해요. 우선순위 설정은 결과가 크게 달라질 수 있어서 중요한데요, 기본값이 모든 상황에 항상 최선이지는 않아요.

사용 가능한 스냅샷 복구 우선순위는 다음과 같아요.

  • replica: (기본값) 스냅샷보다 기존 데이터를 우선해요.
  • snapshot: 기존 데이터보다 스냅샷 데이터를 우선해요.
  • no_sync: 별도 동기화 없이 스냅샷을 복구해요.

스냅샷에서 새 컬렉션을 복구하려면 priority를 snapshot으로 설정해야 해요. snapshot 우선순위에서는 스냅샷의 모든 데이터가 클러스터에 복구되고, replica 우선순위 *(기본값)*에서는 빈 컬렉션이 나올 수 있어요. 클러스터의 컬렉션이 포인트를 하나도 포함하지 않았고 그 소스가 우선됐기 때문이에요.

no_sync는 특수한 용도를 위한 것으로 흔히 쓰이지 않아요. 별도 동기화 없이 샤드를 관리하고 클러스터 간에 샤드를 수동으로 전송할 수 있게 해주는데요, 잘못 사용하면 클러스터가 깨진 상태가 될 수 있어요.

URL에서 복구할 때는 요청 본문에 추가 파라미터를 지정해요.

 PUT /collections/{collection_name}/snapshots/recover
 {
   "location": "http://qdrant-node-1:6333/collections/{collection_name}/snapshots/snapshot-2022-10-10.snapshot",
   "priority": "snapshot"
 }
 curl -X POST 'http://qdrant-node-1:6333/collections/{collection_name}/snapshots/upload?priority=snapshot' \
 -H 'api-key: ********' \
 -H 'Content-Type:multipart/form-data' \
 -F 'snapshot=@/path/to/snapshot-2022-10-10.snapshot'
 from qdrant_client import QdrantClient, models
 client = QdrantClient(url="http://qdrant-node-2:6333")
 client.recover_snapshot(
     "{collection_name}",
     "http://qdrant-node-1:6333/collections/{collection_name}/snapshots/snapshot-2022-10-10.snapshot",
     priority=models.SnapshotPriority.SNAPSHOT,
 )
 import { QdrantClient } from "@qdrant/js-client-rest";
 const client = new QdrantClient({ host: "localhost", port: 6333 });
 client.recoverSnapshot("{collection_name}", {
     location: "http://qdrant-node-1:6333/collections/{collection_name}/snapshots/snapshot-2022-10-10.snapshot",
     priority: "snapshot",
 });

전체 스토리지 스냅샷

사용 가능 버전: v0.8.5부터

컬렉션 하나만이 아니라 스토리지 전체(컬렉션 별칭 포함)를 통째로 스냅샷 만들고 싶을 때가 있어요. Qdrant는 그런 용도의 전용 API도 제공해요. 컬렉션 수준 스냅샷과 비슷하지만 collection_name이 필요 없다는 점이 달라요.

전체 스토리지 스냅샷 만들기

 POST /snapshots
 from qdrant_client import QdrantClient
 client = QdrantClient(url="http://localhost:6333")
 client.create_full_snapshot()
 import { QdrantClient } from "@qdrant/js-client-rest";
 const client = new QdrantClient({ host: "localhost", port: 6333 });
 client.createFullSnapshot();
 use qdrant_client::Qdrant;
 let client = Qdrant::from_url("http://localhost:6334").build()?;
 client.create_full_snapshot().await?;
 import io.qdrant.client.QdrantClient;
 import io.qdrant.client.QdrantGrpcClient;
 QdrantClient client = new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
 client.createFullSnapshotAsync().get();
 using Qdrant.Client;
 var client = new QdrantClient("localhost", 6334);
 await client.CreateFullSnapshotAsync();
 import (
     "context"
     "github.com/qdrant/go-client/qdrant"
 )
 client, err := qdrant.NewClient(&qdrant.Config{
     Host: "localhost",
     Port: 6334,
 })
 client.CreateFullSnapshot(context.Background())

전체 스토리지 스냅샷 삭제

사용 가능 버전: v1.0.0부터

 DELETE /snapshots/{snapshot_name}
 from qdrant_client import QdrantClient
 client = QdrantClient(url="http://localhost:6333")
 client.delete_full_snapshot(snapshot_name="{snapshot_name}")
 import { QdrantClient } from "@qdrant/js-client-rest";
 const client = new QdrantClient({ host: "localhost", port: 6333 });
 client.deleteFullSnapshot("{snapshot_name}");
 use qdrant_client::Qdrant;
 let client = Qdrant::from_url("http://localhost:6334").build()?;
 client.delete_full_snapshot("{snapshot_name}").await?;
 import io.qdrant.client.QdrantClient;
 import io.qdrant.client.QdrantGrpcClient;
 QdrantClient client = new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
 client.deleteFullSnapshotAsync("{snapshot_name}").get();
 using Qdrant.Client;
 var client = new QdrantClient("localhost", 6334);
 await client.DeleteFullSnapshotAsync("{snapshot_name}");
 import (
     "context"
     "github.com/qdrant/go-client/qdrant"
 )
 client, err := qdrant.NewClient(&qdrant.Config{
     Host: "localhost",
     Port: 6334,
 })
 client.DeleteFullSnapshot(context.Background(), "{snapshot_name}")

전체 스토리지 스냅샷 목록 조회

 GET /snapshots
 from qdrant_client import QdrantClient
 client = QdrantClient("localhost", port=6333)
 client.list_full_snapshots()
 import { QdrantClient } from "@qdrant/js-client-rest";
 const client = new QdrantClient({ host: "localhost", port: 6333 });
 client.listFullSnapshots();
 use qdrant_client::Qdrant;
 let client = Qdrant::from_url("http://localhost:6334").build()?;
 client.list_full_snapshots().await?;
 import io.qdrant.client.QdrantClient;
 import io.qdrant.client.QdrantGrpcClient;
 QdrantClient client = new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
 client.listFullSnapshotAsync().get();
 using Qdrant.Client;
 var client = new QdrantClient("localhost", 6334);
 await client.ListFullSnapshotsAsync();
 import (
     "context"
     "github.com/qdrant/go-client/qdrant"
 )
 client, err := qdrant.NewClient(&qdrant.Config{
     Host: "localhost",
     Port: 6334,
 })
 client.ListFullSnapshots(context.Background())

전체 스토리지 스냅샷 다운로드

 GET /snapshots/{snapshot_name}

전체 스토리지 스냅샷 복구

전체 스토리지 스냅샷은 시작 시점에 Qdrant CLI로만 복구할 수 있어요.

예를 들어:

 ./qdrant --storage-snapshot /snapshots/full-snapshot-2022-07-18-11-20-51.snapshot

저장소

생성·업로드·복구된 스냅샷은 .snapshot 파일로 저장돼요. 기본적으로 로컬 파일 시스템에 저장되며, 대신 S3 스토리지 서비스를 사용하도록 구성할 수도 있어요.

로컬 파일 시스템

기본적으로 스냅샷은 ./snapshots에 저장되며, Docker 이미지를 쓸 때는 /qdrant/snapshots에 저장돼요.

대상 디렉터리는 설정을 통해 제어할 수 있어요.

 storage:
   # 스냅샷을 저장할 위치를 지정하세요.
   snapshots_path: ./snapshots

환경 변수 QDRANT__STORAGE__SNAPSHOTS_PATH=./snapshots를 써도 돼요.

사용 가능 버전: v1.3.0부터

스냅샷을 만드는 동안 임시 파일은 기본적으로 설정된 저장 디렉터리에 놓여요. 용량이 부족하거나 네트워크 연결 디스크가 느린 경우엔 임시 파일을 위한 별도 위치를 지정할 수 있어요.

 storage:
   # 임시 파일을 저장할 위치
   temp_path: /tmp

S3

사용 가능 버전: v1.10.0부터

스냅샷을 로컬 파일 시스템 대신 S3 호환 스토리지 서비스에 저장하도록 구성할 수도 있어요. 이 기능을 쓰려면 설정 파일에서 구성해야 해요.

예를 들어, AWS S3를 구성하려면:

 storage:
   snapshots_config:
     # 스냅샷을 S3에 저장하려면 's3'를 사용하세요.
     snapshots_storage: s3
     s3_config:
       # 버킷 이름
       bucket: your_bucket_here
       # 버킷 리전 (예: eu-central-1)
       region: your_bucket_region_here
       # 스토리지 액세스 키
       # 여기 또는 `QDRANT__STORAGE__SNAPSHOTS_CONFIG__S3_CONFIG__ACCESS_KEY` 환경 변수로 지정할 수 있습니다.
       access_key: your_access_key_here
       # 스토리지 시크릿 키
       # 여기 또는 `QDRANT__STORAGE__SNAPSHOTS_CONFIG__S3_CONFIG__SECRET_KEY` 환경 변수로 지정할 수 있습니다.
       secret_key: your_secret_key_here
       # S3 호환 스토리지 URL
       # 여기 또는 `QDRANT__STORAGE__SNAPSHOTS_CONFIG__S3_CONFIG__ENDPOINT_URL` 환경 변수로 지정할 수 있습니다.
       endpoint_url: your_url_here

스냅샷 외에도 Qdrant는 다음을 지원하는 Qdrant 마이그레이션 도구를 제공해요.

  • Qdrant Cloud 인스턴스 간 마이그레이션.
  • 다른 제공자의 벡터를 Qdrant로 마이그레이션.
  • Qdrant OSS에서 Qdrant Cloud로 마이그레이션.

Qdrant 마이그레이션 도구를 효과적으로 쓰는 방법은 마이그레이션 가이드를 참고하세요.