使用快照备份和恢复 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
以确保快照优先于节点上存储的数据。您可以在文档中阅读更多关于优先级的说明。