使用快照备份和恢复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)

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

(Optional) Create collection and import data

加载数据集

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

加载数据集非常简单:

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
Response
{
  "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问题。