使用快照备份与恢复 Qdrant
| 耗时:20 分钟 | 级别:新手 |
|---|
集合(Collection)是 Qdrant 中数据存储的基本单元。它包含向量、向量 ID 以及有效载荷(payload)。然而,为了保持搜索的高效性,需要在数据之上构建额外的数据结构。构建这些数据结构可能需要一些时间,尤其是对于大型集合而言。这就是为什么使用快照是导出和导入 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 数据集的 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)
单个有效载荷(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-snapshot.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-snapshot.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-snapshot.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-snapshot.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-snapshot.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-snapshot.snapshot'
重要提示: 我们选择了 priority=snapshot,以确保优先使用快照而非节点上存储的现有数据。您可以在文档中阅读有关优先级的更多信息。
除了快照之外,Qdrant 还提供了 Qdrant 迁移工具,支持:
- Qdrant Cloud 实例之间的迁移。
- 从其他提供商迁移向量数据到 Qdrant。
- 从 Qdrant OSS 迁移到 Qdrant Cloud。
请遵循我们的迁移指南,了解如何有效使用 Qdrant 迁移工具。