12 KiB
12 KiB
Qdrant 故障排查指南
安装问题
Docker 问题
错误:Cannot connect to Docker daemon
修复:
# 启动 Docker 守护进程
sudo systemctl start docker
# 或在 Mac/Windows 上使用 Docker Desktop
open -a Docker
错误:Port 6333 already in use
修复:
# 查找占用端口的进程
lsof -i :6333
# 终止进程或使用其他端口
docker run -p 6334:6333 qdrant/qdrant
Python 客户端问题
错误:ModuleNotFoundError: No module named 'qdrant_client'
修复:
pip install qdrant-client
# 指定版本
pip install qdrant-client>=1.12.0
错误:grpc._channel._InactiveRpcError
修复:
# 安装带 gRPC 支持的版本
pip install 'qdrant-client[grpc]'
# 或禁用 gRPC
client = QdrantClient(host="localhost", port=6333, prefer_grpc=False)
连接问题
无法连接到服务器
错误:ConnectionRefusedError: [Errno 111] Connection refused
解决方案:
- 检查服务器是否在运行:
docker ps | grep qdrant
curl http://localhost:6333/healthz
- 验证端口绑定:
# 检查监听端口
netstat -tlnp | grep 6333
# Docker 端口映射
docker port <container_id>
- 使用正确的主机地址:
# Linux 上的 Docker
client = QdrantClient(host="localhost", port=6333)
# Mac/Windows 上有网络问题的 Docker
client = QdrantClient(host="127.0.0.1", port=6333)
# Docker 网络内部
client = QdrantClient(host="qdrant", port=6333)
超时错误
错误:TimeoutError: Connection timed out
修复:
# 增加超时时间
client = QdrantClient(
host="localhost",
port=6333,
timeout=60 # 秒
)
# 对于大型操作
client.upsert(
collection_name="documents",
points=large_batch,
wait=False # 不等待索引完成
)
SSL/TLS 错误
错误:ssl.SSLCertVerificationError
修复:
# Qdrant Cloud
client = QdrantClient(
url="https://cluster.cloud.qdrant.io",
api_key="your-api-key"
)
# 自签名证书
client = QdrantClient(
host="localhost",
port=6333,
https=True,
verify=False # 禁用验证(不推荐用于生产环境)
)
集合问题
集合已存在
错误:ValueError: Collection 'documents' already exists
修复:
# 创建前先检查
collections = client.get_collections().collections
names = [c.name for c in collections]
if "documents" not in names:
client.create_collection(...)
# 或重新创建
client.recreate_collection(
collection_name="documents",
vectors_config=VectorParams(size=384, distance=Distance.COSINE)
)
集合未找到
错误:NotFoundException: Collection 'docs' not found
修复:
# 列出可用集合
collections = client.get_collections()
print([c.name for c in collections.collections])
# 检查确切名称(区分大小写)
try:
info = client.get_collection("documents")
except Exception as e:
print(f"未找到集合:{e}")
向量维度不匹配
错误:ValueError: Vector dimension mismatch. Expected 384, got 768
修复:
# 检查集合配置
info = client.get_collection("documents")
print(f"期望维度:{info.config.params.vectors.size}")
# 使用正确维度重新创建
client.recreate_collection(
collection_name="documents",
vectors_config=VectorParams(size=768, distance=Distance.COSINE) # 匹配你的嵌入向量
)
搜索问题
搜索结果为空
问题:搜索返回空结果。
解决方案:
- 验证数据是否存在:
info = client.get_collection("documents")
print(f"点数:{info.points_count}")
# 滚动查看数据
points, _ = client.scroll(
collection_name="documents",
limit=10,
with_payload=True
)
print(points)
- 检查向量格式:
# 必须为浮点数列表
query_vector = embedding.tolist() # 将 numpy 转换为列表
# 检查维度
print(f"查询维度:{len(query_vector)}")
- 验证过滤条件:
# 先不使用过滤器进行测试
results = client.search(
collection_name="documents",
query_vector=query,
limit=10
# 无过滤器
)
# 然后逐步添加过滤器
搜索性能缓慢
问题:搜索耗时过长。
解决方案:
- 创建载荷索引:
# 为过滤器中使用的字段建立索引
client.create_payload_index(
collection_name="documents",
field_name="category",
field_schema="keyword"
)
- 启用量化:
client.update_collection(
collection_name="documents",
quantization_config=ScalarQuantization(
scalar=ScalarQuantizationConfig(type=ScalarType.INT8)
)
)
- 调整 HNSW 参数:
# 更快搜索(精度较低)
client.update_collection(
collection_name="documents",
hnsw_config=HnswConfigDiff(ef_construct=64, m=8)
)
# 使用 ef 搜索参数
results = client.search(
collection_name="documents",
query_vector=query,
search_params={"hnsw_ef": 64}, # 值越小越快
limit=10
)
- 使用 gRPC:
client = QdrantClient(
host="localhost",
port=6333,
grpc_port=6334,
prefer_grpc=True
)
结果不一致
问题:相同查询返回不同结果。
解决方案:
- 等待索引完成:
client.upsert(
collection_name="documents",
points=points,
wait=True # 等待索引更新
)
- 检查副本一致性:
# 强一致性读取
results = client.search(
collection_name="documents",
query_vector=query,
consistency="all" # 从所有副本读取
)
数据写入问题
批量写入失败
错误:PayloadError: Payload too large
修复:
# 拆分为更小的批次
def batch_upsert(client, collection, points, batch_size=100):
for i in range(0, len(points), batch_size):
batch = points[i:i + batch_size]
client.upsert(
collection_name=collection,
points=batch,
wait=True
)
batch_upsert(client, "documents", large_points_list)
无效的 Point ID
错误:ValueError: Invalid point ID
修复:
# 有效的 ID 类型:int 或 UUID 字符串
from uuid import uuid4
# 整数 ID
PointStruct(id=123, vector=vec, payload={})
# UUID 字符串
PointStruct(id=str(uuid4()), vector=vec, payload={})
# 无效的 ID
PointStruct(id="custom-string-123", ...) # 请使用 UUID 格式
载荷验证错误
错误:ValidationError: Invalid payload
修复:
# 确保载荷是 JSON 可序列化的
import json
payload = {
"title": "Document",
"count": 42,
"tags": ["a", "b"],
"nested": {"key": "value"}
}
# 写入前进行验证
json.dumps(payload) # 不应抛出异常
# 避免不可序列化的类型
# 无效:datetime、numpy 数组、自定义对象
payload = {
"timestamp": datetime.now().isoformat(), # 转换为字符串
"vector": embedding.tolist() # 将 numpy 转换为列表
}
内存问题
内存不足
错误:MemoryError 或容器被终止
解决方案:
- 启用磁盘存储:
client.create_collection(
collection_name="large_collection",
vectors_config=VectorParams(size=384, distance=Distance.COSINE),
on_disk_payload=True, # 将载荷存储在磁盘上
hnsw_config=HnswConfigDiff(on_disk=True) # 将 HNSW 存储在磁盘上
)
- 使用量化:
# 减少 4 倍内存
client.update_collection(
collection_name="large_collection",
quantization_config=ScalarQuantization(
scalar=ScalarQuantizationConfig(
type=ScalarType.INT8,
always_ram=False # 保留在磁盘上
)
)
)
- 增加 Docker 内存限制:
docker run -m 8g -p 6333:6333 qdrant/qdrant
- 配置 Qdrant 存储:
# config.yaml
storage:
performance:
max_search_threads: 2
optimizers:
memmap_threshold_kb: 20000
索引期间内存占用高
修复:
# 增加批量加载的索引阈值
client.update_collection(
collection_name="documents",
optimizer_config={
"indexing_threshold": 50000 # 延迟索引
}
)
# 批量插入
client.upsert(collection_name="documents", points=all_points, wait=False)
# 然后优化
client.update_collection(
collection_name="documents",
optimizer_config={
"indexing_threshold": 10000 # 恢复常规索引
}
)
集群问题
节点无法加入集群
问题:新节点无法加入集群。
修复:
# 检查网络连通性
docker exec qdrant-node-2 ping qdrant-node-1
# 验证引导 URL
docker logs qdrant-node-2 | grep bootstrap
# 检查 Raft 状态
curl http://localhost:6333/cluster
脑裂
问题:集群状态不一致。
修复:
# 强制领导者选举
curl -X POST http://localhost:6333/cluster/recover
# 或重启少数节点
docker restart qdrant-node-2 qdrant-node-3
复制延迟
问题:副本落后。
修复:
# 检查集合状态
info = client.get_collection("documents")
print(f"状态:{info.status}")
# 对关键写入使用强一致性
client.upsert(
collection_name="documents",
points=points,
ordering=WriteOrdering.STRONG
)
性能调优
基准测试配置
import time
import numpy as np
def benchmark_search(client, collection, n_queries=100, dimension=384):
# 生成随机查询
queries = [np.random.rand(dimension).tolist() for _ in range(n_queries)]
# 预热
for q in queries[:10]:
client.search(collection_name=collection, query_vector=q, limit=10)
# 基准测试
start = time.perf_counter()
for q in queries:
client.search(collection_name=collection, query_vector=q, limit=10)
elapsed = time.perf_counter() - start
print(f"QPS:{n_queries / elapsed:.2f}")
print(f"延迟:{elapsed / n_queries * 1000:.2f}ms")
benchmark_search(client, "documents")
最优 HNSW 参数
# 高召回率(较慢)
client.create_collection(
collection_name="high_recall",
vectors_config=VectorParams(size=384, distance=Distance.COSINE),
hnsw_config=HnswConfigDiff(
m=32, # 更多连接
ef_construct=200 # 更高构建质量
)
)
# 高速度(较低召回率)
client.create_collection(
collection_name="high_speed",
vectors_config=VectorParams(size=384, distance=Distance.COSINE),
hnsw_config=HnswConfigDiff(
m=8, # 更少连接
ef_construct=64 # 较低构建质量
)
)
# 均衡配置
client.create_collection(
collection_name="balanced",
vectors_config=VectorParams(size=384, distance=Distance.COSINE),
hnsw_config=HnswConfigDiff(
m=16, # 默认值
ef_construct=100 # 默认值
)
)
调试技巧
启用详细日志
import logging
logging.basicConfig(level=logging.DEBUG)
logging.getLogger("qdrant_client").setLevel(logging.DEBUG)
查看服务器日志
# Docker 日志
docker logs -f qdrant
# 带时间戳
docker logs --timestamps qdrant
# 最后 100 行
docker logs --tail 100 qdrant
检查集合状态
# 集合信息
info = client.get_collection("documents")
print(f"状态:{info.status}")
print(f"点数:{info.points_count}")
print(f"分段数:{len(info.segments)}")
print(f"配置:{info.config}")
# 采样数据点
points, _ = client.scroll(
collection_name="documents",
limit=5,
with_payload=True,
with_vectors=True
)
for p in points:
print(f"ID:{p.id},载荷:{p.payload}")
测试连接
def test_connection(host="localhost", port=6333):
try:
client = QdrantClient(host=host, port=port, timeout=5)
collections = client.get_collections()
print(f"已连接!集合数:{len(collections.collections)}")
return True
except Exception as e:
print(f"连接失败:{e}")
return False
test_connection()
获取帮助
- 文档:https://qdrant.tech/documentation/
- GitHub Issues:https://github.com/qdrant/qdrant/issues
- Discord:https://discord.gg/qdrant
- Stack Overflow:标签
qdrant
报告问题
请包含以下信息:
- Qdrant 版本:
curl http://localhost:6333/ - Python 客户端版本:
pip show qdrant-client - 完整的错误回溯信息
- 最小可复现代码
- 集合配置