RAG系统 高级 RAG Milvus 向量数据库 分布式

Milvus生产部署:构建分布式向量搜索平台

AIEng Hub
阅读约 30 分钟

引言

Milvus 是当前最流行的开源分布式向量数据库,专为大规模向量检索场景设计。相比 Pinecone(全托管)和 Chroma(轻量级),Milvus 的优势在于:分布式架构、百亿级向量支持、丰富的索引类型和灵活的部署方式。

┌────────────────────────────────────────────────────────────┐
│                    Milvus 分布式架构                          │
├────────────────────────────────────────────────────────────┤
│                                                             │
│   ┌─────────┐  ┌─────────┐  ┌─────────┐                    │
│   │   SDK    │  │   SDK   │  │   SDK   │                    │
│   └────┬────┘  └────┬────┘  └────┬────┘                    │
│        │            │            │                          │
│        └────────────┼────────────┘                          │
│                     ▼                                       │
│            ┌────────────────┐                               │
│            │   Proxy 节点   │  (负载均衡 + 请求路由)         │
│            └───────┬────────┘                               │
│                    │                                        │
│         ┌──────────┴──────────┐                             │
│         ▼                     ▼                             │
│  ┌─────────────┐     ┌──────────────┐                      │
│  │  Query节点   │     │   Index节点   │                     │
│  │  (检索服务)  │     │  (索引构建)   │                     │
│  └──────┬──────┘     └──────┬───────┘                      │
│         │                   │                               │
│         └─────────┬─────────┘                               │
│                   ▼                                         │
│          ┌────────────────┐                                 │
│          │   Data节点      │  (数据持久化)                    │
│          └───────┬────────┘                                 │
│                  │                                          │
│                  ▼                                          │
│          ┌────────────────┐                                 │
│          │  对象存储/S3    │  (Etcd + MinIO/S3)              │
│          └────────────────┘                                 │
└────────────────────────────────────────────────────────────┘

一、核心架构组件

组件角色说明
Proxy接入层请求路由、负载均衡、权限校验
Query检索层执行向量检索、标量过滤
Index索引层构建和管理向量索引(CPU/GPU)
Data数据层数据持久化、增量/全量合并
Etcd元数据管理集群协调、节点发现
MinIO/S3存储层数据文件和索引文件持久化

二、部署方案

2.1 Docker Compose(开发/测试)

# docker-compose.yml
version: '3.5'

services:
  etcd:
    image: quay.io/coreos/etcd:v3.5.5
    environment:
      - ETCD_AUTO_COMPACTION_MODE=revision
      - ETCD_AUTO_COMPACTION_RETENTION=1000
      - ETCD_QUOTA_BACKEND_BYTES=4294967296

  minio:
    image: minio/minio:RELEASE.2023-03-20T20-16-18Z
    environment:
      MINIO_ACCESS_KEY: minioadmin
      MINIO_SECRET_KEY: minioadmin
    volumes:
      - ./volumes/minio:/minio_data
    command: minio server /minio_data

  milvus:
    image: milvusdb/milvus:v2.4.0
    command: ["milvus", "run", "standalone"]
    environment:
      ETCD_ENDPOINTS: etcd:2379
      MINIO_ADDRESS: minio:9000
    ports:
      - "19530:19530"
    depends_on:
      - etcd
      - minio

volumes:
  minio_data:

2.2 Kubernetes 生产部署

# milvus-helm-values.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: milvus-config
data:
  milvus.yaml: |
    proxy:
      port: 19530
      timeTickInterval: 200
    rootCoord:
      port: 53100
    queryCoord:
      port: 53101
      enableActiveStandby: true
    indexCoord:
      port: 53102
    dataCoord:
      port: 53103
---
# Helm 安装
# helm repo add milvus https://milvus-io.github.io/milvus-helm/
# helm install my-milvus milvus/milvus \
#   --set cluster.enabled=true \
#   --set persistence.enabled=true \
#   --set persistence.storageClass=gp2

三、索引类型与选择

3.1 Milvus 支持的索引

索引类型算法适用场景精度构建速度内存占用
IVF_FLAT倒排索引精度优先
IVF_SQ8量化索引内存优先
IVF_PQ乘积量化极致压缩极低
HNSW分层导航图速度优先极高极高
DISKANN磁盘索引超大容量
AUTOINDEX自动选择简化管理最佳自动动态

3.2 索引选择示例

from pymilvus import (
    connections, Collection, FieldSchema,
    CollectionSchema, DataType, IndexType
)

# 创建集合
fields = [
    FieldSchema(name="id", dtype=DataType.INT64, is_primary=True),
    FieldSchema(name="embedding", dtype=DataType.FLOAT_VECTOR, dim=768),
    FieldSchema(name="title", dtype=DataType.VARCHAR, max_length=256),
    FieldSchema(name="category", dtype=DataType.VARCHAR, max_length=64),
    FieldSchema(name="content", dtype=DataType.VARCHAR, max_length=65535),
]
schema = CollectionSchema(fields, description="RAG文档集合")
collection = Collection(name="rag_docs", schema=schema)

# 创建 HNSW 索引(推荐用于高精度检索)
index_params = {
    "metric_type": "COSINE",
    "index_type": "HNSW",
    "params": {
        "M": 16,          # 每个节点的最大连接数(8-64)
        "efConstruction": 200  # 构建时的搜索范围(100-500)
    }
}
collection.create_index(
    field_name="embedding",
    index_params=index_params
)

3.3 索引参数调优

def choose_index_params(
    total_vectors: int,
    memory_gb: int,
    precision_requirement: str
) -> dict:
    """根据场景推荐索引参数"""
    params = {
        "metric_type": "COSINE"
    }

    if total_vectors < 1_000_000:
        params["index_type"] = "HNSW"
        params["params"] = {"M": 16, "efConstruction": 200}
    elif total_vectors < 10_000_000:
        if memory_gb >= 64:
            params["index_type"] = "HNSW"
            params["params"] = {"M": 24, "efConstruction": 300}
        else:
            params["index_type"] = "IVF_SQ8"
            params["params"] = {"nlist": 4096}
    else:
        params["index_type"] = "DISKANN"
        params["params"] = {}

    return params

四、数据操作

4.1 写入与插入

import numpy as np
from pymilvus import Collection, utility

# 连接
connections.connect(
    host="localhost",
    port="19530",
    alias="default"
)

# 插入数据
collection = Collection("rag_docs")
collection.load()

def batch_insert(
    collection,
    embeddings: np.ndarray,
    texts: list[str],
    metadata: list[dict],
    batch_size: int = 1000
):
    """批量插入数据"""
    total = len(embeddings)
    for i in range(0, total, batch_size):
        end = min(i + batch_size, total)
        mr = collection.insert([
            list(range(i, end)),
            embeddings[i:end].tolist(),
            [m["title"] for m in metadata[i:end]],
            [m["category"] for m in metadata[i:end]],
            texts[i:end]
        ])
        print(f"已插入 {end}/{total}, 耗时: {mr}")
    collection.flush()

4.2 检索查询

def search_with_params(
    collection: Collection,
    query_vector: list[float],
    top_k: int = 10,
    expr: str = None,
    params: dict = None
):
    """带参数的高级检索"""
    search_params = params or {
        "metric_type": "COSINE",
        "params": {"ef": 64}  # HNSW 搜索宽度
    }

    results = collection.search(
        data=[query_vector],
        anns_field="embedding",
        param=search_params,
        limit=top_k,
        expr=expr,  # 标量过滤表达式
        output_fields=["title", "category", "content"]
    )

    for hit in results[0]:
        print(f"距离: {hit.distance:.4f}")
        print(f"内容: {hit.entity.get('title')}")
        print(f"类别: {hit.entity.get('category')}")

    return results

4.3 混合检索(向量 + 标量过滤)

# 类别过滤 + 向量检索
results = search_with_params(
    collection,
    query_vector,
    top_k=10,
    expr='category in ["technology", "science"]',
    params={"metric_type": "COSINE", "params": {"ef": 64}}
)

# 范围过滤
results = search_with_params(
    collection,
    query_vector,
    top_k=10,
    expr='id > 1000'
)

五、生产运维

5.1 性能优化

优化项配置效果
增加 Query 节点数queryNode.replicas: 3提升并发查询能力
使用 GPU 索引indexNode.enableGPU: true加速索引构建
调整 Segment 大小dataCoord.segment.maxSize: 2048减少小文件
启用压缩dataCoord.compaction.enable: true优化存储利用率
缓存预热预加载热点集合减少冷启动延迟

5.2 监控告警

# 启用 Prometheus 监控
helm install prometheus prometheus-community/kube-prometheus-stack \
  --set grafana.enabled=true

# Milvus 内置指标
# - query latency (P50/P95/P99)
# - index build duration
# - memory/disk usage per node
# - request QPS
# - cache hit ratio

5.3 数据备份

# 创建快照
from pymilvus import utility

# 备份集合
utility.create_snapshot(
    collection_name="rag_docs",
    backup_name="daily_backup_20250509"
)

# 列出备份
print(utility.list_snapshots(collection_name="rag_docs"))

六、扩缩容

# 水平扩展 Query 节点
helm upgrade my-milvus milvus/milvus \
  --set queryNode.replicas=5

# 扩缩存储(调整 Data 节点)
helm upgrade my-milvus milvus/milvus \
  --set dataNode.replicas=3

# 垂直扩展(调整资源)
helm upgrade my-milvus milvus/milvus \
  --set queryNode.resources.requests.memory=16Gi \
  --set queryNode.resources.limits.memory=32Gi

七、Milvus 适用场景对比

场景MilvusPineconeChroma
百亿级向量✅ 最佳❌ 成本高❌ 不支持
自建私有云✅ 完美❌ 不支持✅ 但有限
快速原型❌ 部署复杂✅ 最佳✅ 最佳
混合检索✅ 丰富✅ 中等❌ 基础
GPU 加速✅ 支持❌ 不支持❌ 不支持
多租户✅ 支持✅ 支持❌ 不支持

八、总结

Milvus 最适合的场景:

  • 大规模向量检索(百万到百亿级)
  • 企业自建私有云,对数据主权有要求
  • 复杂检索需求(混合检索、多向量字段)
  • 有 Kubernetes 运维能力的团队
  • 对性能和扩展性有极致要求

相关资源: