使用快照备份和恢复 Qdrant 集合

时间:20 分钟级别:初级

集合是 Qdrant 中数据存储的基本单位。它包含向量、它们的 ID 和载荷。然而,为了保持高效的搜索,需要在数据之上构建额外的数据结构。构建这些数据结构可能需要一些时间,特别是对于大型集合。这就是为什么使用快照是导出和导入 Qdrant 集合的最佳方式,因为它们包含了高效恢复整个集合所需的所有组成部分。

本教程将向您展示如何创建集合的快照并恢复它。由于在分布式环境中处理快照可能被认为稍微复杂一些,我们将使用一个 3 节点 Qdrant 集群。但是,同样的方法也适用于单节点设置。

您可以使用本页面中描述的技术来迁移集群。按照本教程中的说明创建和下载快照。当您从快照恢复时,将您的数据恢复到新集群。

先决条件

我们假设您已经有一个正在运行的 Qdrant 实例或集群。如果还没有,您可以按照安装指南来设置本地 Qdrant 实例,或者使用Qdrant Cloud通过几次点击创建集群。

一旦集群运行起来,让我们安装所需的依赖项

pip install qdrant-client datasets

建立与 Qdrant 的连接

我们将使用 Python SDK 和原始 HTTP 调用与 Qdrant 交互。由于我们将使用一个 3 节点集群,我们需要知道所有节点的 URL。为了简单起见,让我们将它们以及 API 密钥都保存在常量中,以便以后引用。

QDRANT_MAIN_URL = "https://my-cluster.com:6333"
QDRANT_NODES = (
    "https://node-0.my-cluster.com:6333",
    "https://node-1.my-cluster.com:6333",
    "https://node-2.my-cluster.com:6333",
)
QDRANT_API_KEY = "my-api-key"

我们现在可以创建一个客户端实例

from qdrant_client import QdrantClient

client = QdrantClient(QDRANT_MAIN_URL, api_key=QDRANT_API_KEY)

首先,我们将从一个预计算的数据集创建一个集合。如果您已经有一个集合,可以跳过此步骤,直接创建快照

(可选)创建集合并导入数据

加载数据集

我们将使用一个包含预计算嵌入的数据集,该数据集可在 Hugging Face Hub 上获取。该数据集名为Qdrant/arxiv-titles-instructorxl-embeddings,使用InstructorXL模型创建。它包含来自arXiv数据集的论文标题的 2.25M 个嵌入。

加载数据集就像这样简单

from datasets import load_dataset

dataset = load_dataset(
    "Qdrant/arxiv-titles-instructorxl-embeddings", split="train", streaming=True
)

我们使用了流模式,因此数据集不会加载到内存中。相反,我们可以迭代它并提取 ID 和向量嵌入。

for payload in dataset:
    id_ = payload.pop("id")
    vector = payload.pop("vector")
    print(id_, vector, payload)

单个载荷看起来像这样

{
  'title': 'Dynamics of partially localized brane systems',
  'DOI': '1109.1415'
}

创建一个集合

首先,我们需要创建我们的集合。我们不打算调整它的配置,但现在创建它是很有意义的。配置也是集合快照的一部分。

from qdrant_client import models

if not client.collection_exists("test_collection"):
    client.create_collection(
        collection_name="test_collection",
        vectors_config=models.VectorParams(
            size=768,  # Size of the embedding vector generated by the InstructorXL model
            distance=models.Distance.COSINE
        ),
    )

上传数据集

计算嵌入通常是向量搜索流水线的瓶颈,但我们很高兴它们已经准备好了。由于本教程的目标是展示如何创建快照,我们将只上传数据集的一小部分

ids, vectors, payloads = [], [], []
for payload in dataset:
    id_ = payload.pop("id")
    vector = payload.pop("vector")

    ids.append(id_)
    vectors.append(vector)
    payloads.append(payload)

    # We are going to upload only 1000 vectors
    if len(ids) == 1000:
        break

client.upsert(
    collection_name="test_collection",
    points=models.Batch(
        ids=ids,
        vectors=vectors,
        payloads=payloads,
    ),
)

我们的集合现在可以用于搜索了。让我们为它创建一个快照。

如果您已经有一个集合,可以跳过上一步,直接创建快照

创建和下载快照

Qdrant 暴露了一个 HTTP 端点来请求创建快照,但我们也可以使用 Python SDK 调用它。我们的设置包含 3 个节点,因此我们需要在它们每一个上调用该端点,并在每个节点上创建快照。使用 Python SDK 时,这意味着为每个节点创建一个单独的客户端实例。

snapshot_urls = []
for node_url in QDRANT_NODES:
    node_client = QdrantClient(node_url, api_key=QDRANT_API_KEY)
    snapshot_info = node_client.create_snapshot(collection_name="test_collection")

    snapshot_url = f"{node_url}/collections/test_collection/snapshots/{snapshot_info.name}"
    snapshot_urls.append(snapshot_url)
// for `https://node-0.my-cluster.com:6333`
POST /collections/test_collection/snapshots

// for `https://node-1.my-cluster.com:6333`
POST /collections/test_collection/snapshots

// for `https://node-2.my-cluster.com:6333`
POST /collections/test_collection/snapshots
响应
{
  "result": {
    "name": "test_collection-559032209313046-2024-01-03-13-20-11.snapshot",
    "creation_time": "2024-01-03T13:20:11",
    "size": 18956800
  },
  "status": "ok",
  "time": 0.307644965
}

一旦我们有了快照 URL,就可以下载它们了。请确保在请求头中包含 API 密钥。下载快照只能通过 HTTP API 完成,因此我们将使用 requests 库。

import requests
import os

# Create a directory to store snapshots
os.makedirs("snapshots", exist_ok=True)

local_snapshot_paths = []
for snapshot_url in snapshot_urls:
    snapshot_name = os.path.basename(snapshot_url)
    local_snapshot_path = os.path.join("snapshots", snapshot_name)

    response = requests.get(
        snapshot_url, headers={"api-key": QDRANT_API_KEY}
    )
    with open(local_snapshot_path, "wb") as f:
        response.raise_for_status()
        f.write(response.content)

    local_snapshot_paths.append(local_snapshot_path)

或者,您可以使用 wget 命令

wget https://node-0.my-cluster.com:6333/collections/test_collection/snapshots/test_collection-559032209313046-2024-01-03-13-20-11.snapshot \
    --header="api-key: ${QDRANT_API_KEY}" \
    -O node-0-shapshot.snapshot

wget https://node-1.my-cluster.com:6333/collections/test_collection/snapshots/test_collection-559032209313047-2024-01-03-13-20-12.snapshot \
    --header="api-key: ${QDRANT_API_KEY}" \
    -O node-1-shapshot.snapshot

wget https://node-2.my-cluster.com:6333/collections/test_collection/snapshots/test_collection-559032209313048-2024-01-03-13-20-13.snapshot \
    --header="api-key: ${QDRANT_API_KEY}" \
    -O node-2-shapshot.snapshot

快照现在已存储在本地。我们可以使用它们将集合恢复到另一个 Qdrant 实例,或者将它们视为备份。我们将在同一集群上使用相同的数据创建另一个集合。

从快照恢复

我们全新的快照已准备好进行恢复。通常,它用于将集合迁移到另一个 Qdrant 实例,但我们将使用它在同一集群上创建一个新集合。它将拥有一个不同的名称,即 test_collection_import。我们无需先创建集合,因为它将自动创建。

集合恢复也是在每个节点上单独完成的,但我们的 Python SDK 尚未支持此功能。我们将转而使用 HTTP API,并使用 requests 库向每个节点发送请求。

for node_url, snapshot_path in zip(QDRANT_NODES, local_snapshot_paths):
    snapshot_name = os.path.basename(snapshot_path)
    requests.post(
        f"{node_url}/collections/test_collection_import/snapshots/upload?priority=snapshot",
        headers={
            "api-key": QDRANT_API_KEY,
        },
        files={"snapshot": (snapshot_name, open(snapshot_path, "rb"))},
    )

或者,您可以使用 curl 命令

curl -X POST 'https://node-0.my-cluster.com:6333/collections/test_collection_import/snapshots/upload?priority=snapshot' \
    -H 'api-key: ${QDRANT_API_KEY}' \
    -H 'Content-Type:multipart/form-data' \
    -F 'snapshot=@node-0-shapshot.snapshot'

curl -X POST 'https://node-1.my-cluster.com:6333/collections/test_collection_import/snapshots/upload?priority=snapshot' \
    -H 'api-key: ${QDRANT_API_KEY}' \
    -H 'Content-Type:multipart/form-data' \
    -F 'snapshot=@node-1-shapshot.snapshot'

curl -X POST 'https://node-2.my-cluster.com:6333/collections/test_collection_import/snapshots/upload?priority=snapshot' \
    -H 'api-key: ${QDRANT_API_KEY}' \
    -H 'Content-Type:multipart/form-data' \
    -F 'snapshot=@node-2-shapshot.snapshot'

重要提示: 我们选择了 priority=snapshot 以确保快照优先于节点上存储的数据。您可以在文档中阅读更多关于优先级的说明。

本页有用吗?

感谢您的反馈! 🙏

很抱歉听到这个。😔 您可以在 GitHub 上编辑此页面,或创建一个 GitHub issue。