Снимки состояния#

Снимки состояния — файлы tar-архива, содержащие данные и конфигурацию конкретной коллекции на конкретном узле в конкретный момент времени. При работе с одной коллекцией в распределенной среде, где используются несколько узлов одного кластера, необходимо создавать снимки состояния для каждого узла отдельно.

Эта функция может использоваться для архивирования данных или простого реплицирования существующей развертки.

Предусловия#

Пререквизиты:

  • Доступ к серверу: SSH или физический доступ.

  • Установленный продукт: сервер должен быть запущен (кроме операций с файлами данных).

  • Исходный код: скрипты находятся в /src/bin/ репозитория продукта.

  • Rust: установленный компилятор для сборки утилит.

Привилегии:

  • Файловая система: права на чтение/запись в storage_path.

  • API-ключ: обязателен ключ с правами admin для большинства операций.

  • Сетевой доступ: доступность API-порта (порт по умолчанию 6333).

Ключевые требования:

  • Доступ к хранилищу (S3/etc.) для загрузки/выгрузки.

  • API-ключ.

Последовательность выполнения#

Создание снимка состояния#

Информация

Если осуществляется работа с распределенным развертыванием, необходимо создать снимки состояния для каждого узла отдельно. Один снимок будет содержать только те данные, которые хранятся на узле, где был создан этот снимок.

Чтобы создать новый снимок состояния для существующей коллекции выполните:

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}")

Это синхронная операция, в результате которой создается файл tar-архива в каталоге snapshot_path.

Удаление снимка состояния#

Удаление снимка состояния:

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}")

Получение снимка состояния#

Информация

В настоящее время доступен только через REST API.

Чтобы скачать указанный снимок состояния из коллекции в виде файла:

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'

Восстановление снимка состояния#

Информация

Снимки состояния, созданные в одном кластере Platform V Vector DB (далее - Vector DB), можно восстановить только в другие кластеры Vector DB той же младшей версии. Например, снимок, сделанный в кластере версии v1.4.1, можно восстановить только в кластерах, работающих под управлением версии v1.4.x, где x равно или больше 1.

Снимки состояния можно восстановить тремя способами:

  1. Восстановление из URL-адреса или локального файла (полезно для восстановления файлов снимков, хранящихся на удаленном сервере или уже имеющихся на узле).

  2. Восстановление из загруженного файла (полезно для переноса данных в новый кластер).

  3. Восстановление во время запуска (полезно при запуске экземпляра Vector DB с одним узлом, размещенного самостоятельно).

Независимо от используемого метода, Vector DB извлечет данные шардов из снимка состояния и правильно зарегистрирует шарды в кластере. Если в кластере имеются другие активные реплики восстановленных шардов, Vector DB по умолчанию выполнит их репликацию на вновь восстановленный узел для поддержания согласованности данных.

Восстановление из URL-адреса или локального файла#

Этот метод восстановления требует, чтобы файл снимка состояния был доступен для скачивания по URL-адресу или существовал как локальный файл на узле (например, если ранее был создан снимок состояния на этом узле). Если вместо этого требуется загрузить файл снимка состояния, обратитесь к следующему разделу.

Чтобы восстановить состояние из URL-адреса или локального файла, используйте конечную точку восстановления снимка состояния. Эта точка принимает либо URL-адрес вроде https://example.com, либо URI-файл типа file:///tmp/snapshot-2022-10-10.snapshot. Если целевая коллекция отсутствует, она будет создана.

PUT /collections/{collection_name}/snapshots/recover
{
  "location": "http://qdrant-node-1:6333/collections/{collection_name}/snapshots/snapshot-2022-10-10.shapshot"
}
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.shapshot",
)
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.shapshot",
});

Информация

При восстановлении из URL-адреса указанный URL должен быть доступен для узла Vector DB, который восстанавливается. Можно выполнить восстановление через URI-файл или через загруженный файл.

Восстановление из загруженного файла#

Файл снимка состояния также можно загрузить как файл и восстановить его с помощью функции восстановления из загруженного снимка состояния. Этот интерфейс принимает сырые данные снимка состояния в теле запроса. Если целевая коллекция отсутствует, она будет создана.

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.shapshot'

Обычно этот способ используется для миграции данных между кластерами, поэтому рекомендуется установить приоритет снимок для такого сценария использования.

Восстановление во время старта#

Внимание

Данный метод нельзя использовать в многоузловом развертывании.

Если развернут экземпляр с одним узлом, можно восстановить любую коллекцию при старте, и она сразу станет доступной. Восстановление снимков осуществляется через интерфейс командной строки при запуске с аргументом --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.

Приоритеты снимков состояния#

При восстановлении снимка состояния на непустой узел могут возникнуть конфликты между данными снимка и существующими данными. Параметр «приоритет» определяет, каким образом Vector DB обрабатывает подобные конфликты. Настройка приоритета важна, поскольку разные значения приоритета могут привести к совершенно разным результатам. Значение приоритета по умолчанию может оказаться неподходящим для всех случаев.

Имеются следующие доступные приоритеты восстановления снимков состояния:

  • replica: (по умолчанию) предпочтение отдается существующим данным перед данными снимка;

  • snapshot: предпочтение отдается данным снимка перед существующими данными;

  • no_sync: восстановление снимка без дополнительной синхронизации.

Чтобы восстановить новую коллекцию из снимка состояния, нужно задать приоритет 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.shapshot",
  "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.shapshot'
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.shapshot",
    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.shapshot",
  priority: "snapshot"
});

Снимки состояния всего хранилища#

Иногда бывает удобно сделать снимок состояния не просто отдельной коллекции, но и всего хранилища целиком, включая псевдонимы коллекций. Vector DB предоставляет специальный 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())

Удаление полного снимка хранилища#

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())

Загрузка полного снимка ахранилища#

Информация

На данный момент доступно только через REST API.

GET /snapshots/{snapshot_name}

Восстановление полного снимка хранилища#

Восстановление снимков возможно только через интерфейс командной строки при запуске.

Например:

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

Использование хранилища#

Созданные, загруженные и восстановленные снимки сохраняются в файлах формата .snapshot. По умолчанию они хранятся на локальной файловой системе. Также можно настроить хранение этих файлов в службе хранения S3.

Локальная файловая система#

По умолчанию снимки хранятся в папке ./snapshots.

Целевую директорию можно контролировать через конфигурацию:

storage:
  # Specify where you want to store snapshots.
  snapshots_path: ./snapshots

Также можно указать переменную окружения QDRANT__STORAGE__SNAPSHOTS_PATH=./snapshots.

Пока создается снимок состояния, временные файлы помещаются в настроенное хранилище по умолчанию. Если емкость хранилища ограничена или подключен медленный диск, можно указать отдельное место для временных файлов:

storage:
  # Where to store temporary files
  temp_path: /tmp

S3-хранилище#

Помимо сохранения снимков состояний на локальную файловую систему, доступна возможность настроить сохранение снимков в совместимую службу хранения S3. Чтобы включить эту возможность, ее следует сконфигурировать в файле конфигурации Config.yaml.

Например, чтобы настроить работу с AWS S3:

storage:
  snapshots_config:
    # Use 's3' to store snapshots on S3
    snapshots_storage: s3

    s3_config:
      # Bucket name
      bucket: {your_bucket_here}

      # Bucket region (e.g. eu-central-1)
      region: {your_bucket_region_here}

      # Storage access key
      # Can be specified either here or in the `QDRANT__STORAGE__SNAPSHOTS_CONFIG__S3_CONFIG__ACCESS_KEY` environment variable.
      access_key: {your_access_key_here}

      # Storage secret key
      # Can be specified either here or in the `QDRANT__STORAGE__SNAPSHOTS_CONFIG__S3_CONFIG__SECRET_KEY` environment variable.
      secret_key: {your_secret_key_here}

      # S3-Compatible Storage URL
      # Can be specified either here or in the `QDRANT__STORAGE__SNAPSHOTS_CONFIG__S3_CONFIG__ENDPOINT_URL` environment variable.
      endpoint_url: {your_url_here}

Результат#

Параметр

Результат

Создание снимка

Генерация tar-архива с данными и конфигурацией коллекции на конкретном узле

Удаление снимка

Удаление указанного снимка из хранилища (локального или S3)

Восстановление данных

Восстановление коллекции из снимка с поддержкой приоритетов (snapshot, replica)

Хранение снимков

Поддержка локального хранения и интеграции с S3 для масштабируемости

Полные снимки хранилища

Архивирование всех коллекций и псевдонимов в одном файле (только для кластеров с одним узлом)

  • Функциональность снимков:

    • Архивация: позволяет сохранять состояние коллекции/кластера в любой момент времени.

    • Репликация: используется для миграции данных между кластерами или восстановления после сбоев.

    • Гибкость: поддерживает три метода восстановления (из URL, файла или командной строки).

  • Приоритеты восстановления:

    • snapshot: данные снимка заменяют существующие (используется для перезаписи).

    • replica: существующие данные имеют приоритет (по умолчанию).

    • no_sync: ручное управление шардами без синхронизации (опасно, требует точного знания структуры).

  • Ограничения:

    • Полные снимки хранилища работают только в режиме одного узла.

    • Версия кластера должна совпадать при восстановлении (например, v1.4.x → v1.4.x).

  • Примеры использования:

    • До настройки: отсутствие резервных копий приводит к потере данных при сбое.

    • После настройки: автоматическое создание снимков каждые 24 часа минимизирует риск.