Skip to content

Milvus 架构原理与应用实践

面试结论| Milvus 是面向大规模向量检索的云原生数据库,把接入、协调、流式写入、历史数据查询、离线索引/压缩和持久化存储拆开扩缩。项目中不能把“数据写入成功”等同于“立即能被目标查询看到”,也不能只凭向量规模选择 Milvus;Schema、主键、过滤字段、Consistency、索引、Load、版本与评测集共同决定可用性。

版本与证据边界| 本文依据 Milvus 官方文档和 2.6.19 Release Notes(访问日期:2026-07-14)整理;3.0 当前为 beta,不作为本文生产默认。仓库没有 Milvus 运行代码、集群、压测数据或真实事故,代码与案例均标注为最小示例或故障演练。

目录

1. 学习目标

  • 能解释 Milvus 与向量索引、Vector Store、关系型数据库的边界;
  • 能沿 insert → WAL → growing segment → sealed segment → index → load → search 说明数据生命周期;
  • 能设计 RAG Collection 的主键、向量、正文、版本、租户和 ACL 字段;
  • 能用 PyMilvus 完成建表、建索引、写入、过滤检索与 Dense/Sparse 混合检索;
  • 能根据规模、过滤、事务、运维和 SLO 判断是否应采用 Milvus。

2. 面试结论

2.1 30 秒专业短答

Milvus 本质上是为高维向量相似度检索优化的分布式数据库,主要解决大规模向量的存储、ANN 索引、过滤和水平扩展问题。它通过 Proxy、Coordinator、Streaming Node、Query Node、Data Node 以及共享存储,把实时写入、历史查询和离线索引/Compaction 解耦。它适合向量成为核心负载且团队能承担平台运维的场景;小规模、强事务或复杂 JOIN 场景应先验证 pgvector 或现有搜索平台,并用同一数据集比较 Recall、P99、吞吐、资源和运维成本。

2.2 一分钟复述版

Milvus 不只是“保存 Embedding 的表”。写请求经接入层进入 Streaming Node,先写 WAL,并以 growing data 参与实时查询;数据封存后由 Data Node 完成 Compaction 和索引构建,Query Node 从对象存储加载 sealed data 和索引执行历史查询。Coordinator 负责元数据、拓扑、调度、时间戳和一致性协调,Proxy 聚合分片结果。

在 RAG 中,我会让关系库保留文档、权限和发布状态真值,Milvus 保存可重建的检索投影。Schema 中使用稳定 Chunk ID,显式保存 tenant_idacl_groupdoc_versionembedding_versionis_active,查询时先构造可信过滤表达式,再执行 Dense/Sparse 候选召回。选型关键不是“数据多不多”一个数字,而是同一过滤分布和 SLO 下,专用向量平台是否比现有存储带来可证明的收益。

3. 面试官为什么问

  • 概念边界:是否把向量数据库误当成完整 RAG;
  • 分布式原理:是否理解存算分离、WAL、Segment、Load 和一致性;
  • 工程实现:能否把 Schema、索引、查询参数与业务权限连接起来;
  • 生产意识:是否会用 Recall、P99、资源和故障演练选型,而不是背产品名;
  • 版本意识:是否识别 2.6 新架构文档与旧版组件名之间的差异。

4. 概念、边界与小白解释

小白先这样理解:大型仓储中心的现货区与归档区

一家大型仓储中心每天接收新包裹。前台先核对包裹信息,调度中心决定送往哪条流水线;刚到的包裹放在“现货区”,客户很快就能查到。夜间,工作人员把零散包裹整理成封箱托盘,建立位置目录,再送进大型归档仓。客户查货时,系统既查现货区,也查归档区,最后合并结果。

技术映射如下:

生活场景Milvus 对象作用
前台Proxy校验、路由与聚合请求
调度中心Coordinator管理元数据、拓扑、任务与一致性
现货流水线Streaming Node写 WAL、处理 growing data 与实时查询
归档查询员Query Node加载并搜索 sealed segments
夜间整理员Data NodeCompaction、索引构建等离线任务
托盘Segment数据组织、索引与查询的关键物理单元
总仓库对象存储、Meta Store、WAL保存数据、索引、元数据与写入日志

回到专业机制:Milvus 2.6 的主架构是存算分离和流批分离。实时数据与历史数据走不同执行路径,但一次查询需要对两者归并。类比的边界是:真实分布式系统还涉及时间戳、一致性、分片、副本、失败恢复和多级结果归并,不是人工仓库的简单先后顺序。

4.1 它是什么

Milvus 是开源、云原生、列式组织的向量数据库,提供向量字段、标量字段、ANN/精确索引、Metadata 过滤、Dense/Sparse/多向量搜索、分片副本和水平扩缩能力。

4.2 它不是什么

  • 不是 Embedding 模型;向量质量来自上游模型和数据;
  • 不是完整 RAG;切片、权限真值、重排、上下文和生成需要外部链路;
  • 不是默认业务主库;复杂事务、JOIN、余额和订单真值不应因“检索方便”迁入;
  • 不是只要换成 HNSW 就自动变快;Load、过滤、Segment、并发和资源同样影响性能。

4.3 何时使用与不使用

适合:向量检索是核心负载、数据或吞吐需要独立扩展、需要多向量/混合检索、团队有 Kubernetes/存储/监控能力。

不宜直接采用:Notebook 或小规模 PoC、已有 PostgreSQL/Elastic 足以满足 SLO、业务依赖复杂事务、没有评测集和容量证据、团队无法维护对象存储/WAL/etcd/升级与备份链路。

5. 核心对象与架构原理

5.1 Collection、Field、Entity 与 Schema

Collection 类似表,Field 是列,Entity 是一条记录。显式 Schema 是生产治理边界:字段类型、主键、向量维度和可空性决定写入合法性;动态字段 $meta 适合不稳定附加属性,但高频过滤字段应显式建模并评估标量索引,避免把治理问题藏入 JSON。

RAG 推荐字段:

字段示例类型设计目的
chunk_idVARCHAR 主键稳定幂等、更新与引用定位
doc_idVARCHAR关联源文档
tenant_idVARCHAR租户硬过滤或分区键候选
acl_groupARRAY<VARCHAR> 或规范化标量权限过滤;具体建模需按查询验证
textVARCHAR原文、全文检索输入与结果展示
dense_vectorFLOAT_VECTOR语义召回
sparse_vectorSPARSE_FLOAT_VECTORBM25/学习式稀疏召回
doc_versionINT64文档发布版本
embedding_versionVARCHAR防止新旧向量静默混用
is_activeBOOL发布、撤回与灰度切换

5.2 Partition、Shard、Replica 与 Segment

  • Partition:Collection 内的逻辑数据子集,可缩小管理或查询范围;不能为每个用户无限创建分区。
  • Partition Key:按字段值路由数据,适合高基数租户隔离候选,但需要验证数据倾斜和热点。
  • Shard:写入通道与并行入口;增加 Shard 不是免费加速,会增加调度和资源开销。
  • Replica:查询数据副本,用于读吞吐和可用性;副本增加会放大内存/磁盘和加载成本。
  • Segment:物理数据单元。Growing Segment 服务新写数据;Sealed Segment 适合构建索引、压缩和批量查询。

5.3 写入数据流

  1. SDK/REST 请求由 Proxy 校验和路由;
  2. Streaming Node 将操作写入 WAL,获得持久性和恢复基础;
  3. 新数据处于 growing 状态,可按 Consistency 要求参与搜索;
  4. Segment 达到条件后转为 sealed;
  5. Data Node 执行离线索引和 Compaction,结果存入对象存储;
  6. Query Node 加载新索引并替换对应的 growing 数据视图。

5.4 查询数据流

Proxy 根据路由将请求发往相关 Streaming Node;Streaming Node 查询 growing data,并协调 Query Node 查询 sealed data。各 Segment、Query Node、Streaming Node 和 Proxy 分层归并 TopK,最后返回结果。过滤表达式、Partition、索引类型、Search Params 和 Consistency 都会改变执行成本与可见数据范围。

5.5 Consistency 与“写入后查不到”

Milvus 支持 StrongBoundedSessionEventually 四级一致性,默认是 Bounded Staleness。其核心是把请求映射到 Guarantee Timestamp:查询只有在要求时间戳之前的数据可见后才能执行。

工程判断:

  • 功能测试可用 Strong 避免把可见性延迟误判为数据错误;
  • 同一客户端要求读到自己的写入,可评估 Session;
  • 在线检索通常需要在新鲜度与尾延迟之间实测 Bounded;
  • Eventually 只适合能接受短暂不可见的场景;
  • flush() 主要推动持久化/封存,不应被当作每次写后的通用可见性修复按钮。

6. 技术栈、横向选型与双图

6.1 技术点清单

技术点 ID技术点/环节类型采用方案链路职责版本/证据边界
TP-MV-01部署形态数据基础设施Milvus Standalone 用于学习;Cluster 用于有规模与 HA 证据的生产参考提供向量存储和检索运行时2.6.19;Standalone 不能直接在线升级为 Cluster
TP-MV-02客户端与接口SDK/APIPyMilvus MilvusClient;业务侧再封装 Repository/Adapter建表、写入、搜索、管理Python SDK 2.6.16 与 Milvus 2.6.19 对应关系来自 Release Notes
TP-MV-03向量索引ANN/精确算法FLAT 建基线;HNSW/IVF/DiskANN 按数据与资源验证在 Recall、延迟、内存和构建时间间权衡参数无跨数据集最优值
TP-MV-04混合召回检索算法与服务Dense + BM25 Sparse,RRF 基线兼顾语义与专名/编号词面召回BM25 Function 与 Hybrid Search 为官方能力;质量需项目评测
TP-MV-05权限与过滤数据建模/安全显式租户和 ACL 字段 + 可信 Filter;关系库保留权限真值在 ANN 前缩小允许候选并阻止越权过滤表达式不能由不可信文本直接拼接
TP-MV-06业务真值同步数据集成Outbox/CDC + 幂等投影 + 对账把业务真值异步投影到 Milvus本文为参考设计,仓库无运行证据
TP-MV-07可观测性监控与追踪Prometheus/Grafana + 应用 Trace观测组件、Segment、Load、索引、延迟与错误官方提供指标端点;具体告警阈值需压测基线

6.2 横向选型对比

技术点 ID候选方案优点缺点/代价适用场景不适用场景选择结论与依据
TP-MV-01Standalone部署简单、学习成本低扩展和 HA 有限,不能在线升级为 Cluster本地实验、小负载已确认的大规模生产用最小实验验证接口,不据此推断集群性能
TP-MV-01Cluster组件可独立扩展、适合 HA对象存储、WAL、etcd、K8s 与升级运维复杂大规模、独立平台团队小库、低运维预算压测和故障演练证明必要后采用
TP-MV-02直接 PyMilvusAPI 能力完整、排障透明业务代码容易绑定产品语义基础设施层、诊断工具多引擎切换频繁在基础层使用并封装稳定接口
TP-MV-02LangChain/LlamaIndex AdapterRAG 集成快抽象可能隐藏 Schema、Consistency 和参数原型、统一编排深度调优与故障定位原型可用,生产保留直接 SDK 逃生口
TP-MV-03FLAT精确、可做 Ground Truth全量扫描成本高小库、离线 Recall 基线大规模低延迟必须保留抽样基线
TP-MV-03HNSW/IVF/DiskANN可扩展且有不同资源权衡近似损失、参数和构建/加载成本生产大库无评测集就直接上线用 Recall-P99-资源曲线选择
TP-MV-04Dense Only语义召回直接编号、专名和精确词可能漏召回自然语言意图强技术文档、代码、型号检索作为基线,不默认作为终态
TP-MV-04Dense + BM25 + RRF互补召回、异构分数无需直接相加候选、索引和评测更复杂企业知识、专名与自然语言并存语料极小且精确检索足够作为 RAG 生产参考基线
TP-MV-05预过滤安全边界清晰、减少搜索空间复杂表达式可能成为瓶颈ACL、租户、状态硬约束过滤字段未建模权限必须优先使用硬过滤
TP-MV-05搜索后过滤实现表面简单可能不足 TopK,更不能作为越权防线仅非安全软规则ACL、租户隔离禁止承担安全边界
TP-MV-06Outbox/CDC 投影可追踪、可重放、与业务事务衔接最终一致、需对账和补偿业务库是真值源要求向量库跨表强事务推荐生产参考模式
TP-MV-06应用双写接入快部分成功导致漂移,恢复困难可丢弃实验数据关键文档与权限仅可用于低风险 PoC
TP-MV-07仅应用日志接入简单看不到组件与资源根因本地实验分布式生产不足以支撑生产排障
TP-MV-07Prometheus/Grafana + Trace组件与请求证据可关联指标基数和运维成本Cluster 生产无人维护告警用压测和故障演练建立阈值

6.3 当前架构

图:架构|Milvus 2.6 流批分离与共享存储

替代文本: 客户端经负载均衡和 Proxy 进入 Milvus,Coordinator 管理拓扑、任务和一致性;Streaming Node 处理 WAL、实时写入与 growing 查询,Query Node 查询 sealed data,Data Node 执行索引和 Compaction,三类节点共享元数据、WAL 和对象存储。

图表加载中…

读图结论: Milvus 的扩展能力来自职责拆分,但生产复杂度也来自同一拆分;慢查询、写入积压和索引变慢应分别定位 Query、Streaming、Data 路径,而不是统一“加机器”。

6.4 写入与查询调用链

图:技术调用流程|一次写入到可检索及失败分支

替代文本: 应用写入带版本的 Chunk,Proxy 路由到 Streaming Node 并记录 WAL;数据先以 growing 状态按一致性要求可见,封存后由 Data Node 建索引和压缩,Query Node 加载 sealed 数据;查询同时搜索 growing 与 sealed,若版本、ACL、Load 或超时不满足则拒绝、降级或重试。

图表加载中…

读图结论: “写成功但查不到”必须区分 WAL 持久化、Consistency 可见性、Segment 状态、索引完成和 Load 状态;这些不是同一个成功条件。

7. 最小可运行实践

最小实验边界| 以下代码基于 PyMilvus 2.6.x MilvusClient 风格,需连接本地 Milvus;示例维度为 4,只用于验证 API 和数据流,不能代表生产 Schema 或性能。

7.1 建立 Collection 与 HNSW 索引

python
from pymilvus import DataType, MilvusClient

URI = "http://localhost:19530"
TOKEN = "root:Milvus"  # 仅本地默认示例;生产必须使用密钥管理和最小权限
COLLECTION = "rag_chunks_v1"

client = MilvusClient(uri=URI, token=TOKEN)

schema = MilvusClient.create_schema(
    auto_id=False,
    enable_dynamic_field=False,
)
schema.add_field("chunk_id", DataType.VARCHAR, is_primary=True, max_length=128)
schema.add_field("tenant_id", DataType.VARCHAR, max_length=64)
schema.add_field("doc_id", DataType.VARCHAR, max_length=128)
schema.add_field("doc_version", DataType.INT64)
schema.add_field("embedding_version", DataType.VARCHAR, max_length=64)
schema.add_field("is_active", DataType.BOOL)
schema.add_field("text", DataType.VARCHAR, max_length=4096)
schema.add_field("dense_vector", DataType.FLOAT_VECTOR, dim=4)

indexes = MilvusClient.prepare_index_params()
indexes.add_index(
    field_name="dense_vector",
    index_name="dense_hnsw",
    index_type="HNSW",
    metric_type="COSINE",
    params={"M": 16, "efConstruction": 128},
)

if client.has_collection(COLLECTION):
    client.drop_collection(COLLECTION)  # 仅用于可重复本地实验

client.create_collection(
    collection_name=COLLECTION,
    schema=schema,
    index_params=indexes,
    consistency_level="Session",
)

7.2 幂等写入与可信过滤搜索

python
rows = [
    {
        "chunk_id": "doc-7:v3:chunk-001",
        "tenant_id": "tenant-a",
        "doc_id": "doc-7",
        "doc_version": 3,
        "embedding_version": "embed-v2",
        "is_active": True,
        "text": "退款申请应在订单完成后七日内提交。",
        "dense_vector": [0.11, 0.24, 0.68, 0.19],
    }
]
client.upsert(collection_name=COLLECTION, data=rows)

trusted_tenant = "tenant-a"  # 必须来自认证上下文,不接受模型自由生成
filter_expr = (
    f'tenant_id == "{trusted_tenant}" '
    'and is_active == true '
    'and embedding_version == "embed-v2"'
)

result = client.search(
    collection_name=COLLECTION,
    anns_field="dense_vector",
    data=[[0.10, 0.25, 0.70, 0.18]],
    limit=5,
    filter=filter_expr,
    search_params={"metric_type": "COSINE", "params": {"ef": 64}},
    output_fields=["chunk_id", "doc_id", "doc_version", "text"],
    consistency_level="Session",
)
print(result)

生产代码不能直接把任意租户字符串插入表达式;应白名单校验、使用安全构造器或规范化标识,并在服务端二次授权。M=16efConstruction=128ef=64 只是实验起点,不是推荐终值。

7.3 最小验证断言

python
hits = result[0]
assert hits, "预期至少命中一条当前租户的活动数据"
assert all(hit["entity"]["doc_version"] == 3 for hit in hits)

cross_tenant = client.search(
    collection_name=COLLECTION,
    anns_field="dense_vector",
    data=[[0.10, 0.25, 0.70, 0.18]],
    limit=5,
    filter='tenant_id == "tenant-b" and is_active == true',
    output_fields=["chunk_id"],
)
assert not cross_tenant[0], "tenant-b 不应看到 tenant-a 数据"

8. RAG 应用实践

8.1 推荐边界:双存储而非 Milvus 包办一切

text
关系库:文档、版本、ACL、发布状态、任务与审计真值
Milvus:Chunk + Dense/Sparse Vector + 可过滤 Metadata 的检索投影
对象存储:原文件、解析产物与可复现中间件

通过 Outbox/CDC 或可靠任务生成投影,使用 chunk_id + doc_version + embedding_version 实现幂等。删除采用“真值库先撤权/下线,检索投影异步删除并对账”的方式;安全请求不能等待向量库最终删除才生效。

Milvus 可用 BM25 Function 把文本转换为 Sparse Vector,并通过 hybrid_search() 合并多个 AnnSearchRequest。项目起点应优先使用 RRF,因为 Dense 相似度和 BM25 分数的尺度不同;只有分数经过可靠归一化/校准且有标注集时,才考虑 WeightedRanker。

阶段预算必须分开:

text
k_dense / k_sparse → fusion_top_n → external_rerank_top_n → k_context

Milvus 内置 Reranking 是多路候选融合,不等同于理解 Query-Document 交互的 Cross-Encoder。若任务需要精细相关性判断,应把融合后的有限候选交给外部 Reranker。

8.3 蓝绿索引与版本切换

不在原 Collection 中静默混用不同维度或语义空间的 Embedding。推荐:

  1. 新建 rag_chunks_v2
  2. 从固定语料构建新向量和索引;
  3. 用固定 Query 集比较 Recall、排序、P99 和资源;
  4. 使用 Collection Alias 或服务路由灰度;
  5. 监控版本混用和空召回;
  6. 达标后切换,保留回滚窗口,再回收旧版本。

8.4 实践验收矩阵

场景输入必须证明证据
新写可见Upsert 后立即查询所选 Consistency 满足业务新鲜度write_ts、search_ts、命中 ID、延迟
租户隔离同向量跨 tenant 查询禁止跨租户返回Filter、候选 ID、授权审计
版本切换v1/v2 相同 Query无新旧向量静默混用Collection/Alias、Embedding/Index 版本
ANN 质量FLAT 与 ANN 同批 QueryRecall 损失在门槛内Recall@K、P95/P99、内存、QPS
故障降级Query Node/对象存储异常不把部分结果冒充完整结果错误码、Trace、重试次数、结果标记

9. 难点、亮点与边界

9.1 技术难点

可直接口述: 这个项目最难的不是把向量写进 Milvus,而是在数据持续更新、权限变化和多版本共存的约束下,同时保证检索新鲜度、权限正确性和稳定 P99。我把问题拆成真值与投影边界、Consistency 可见性、Schema/版本治理、ANN 质量和集群资源五层,通过跨租户断言、FLAT 对照、固定 Query 重放和故障注入验证;当前仓库只有设计与最小示例,没有真实压测结论。

9.2 方案亮点

可直接口述: 原来的风险基线是应用双写并在一个 Collection 里覆盖向量,部分失败后无法证明哪一版数据可用。我选择关系库真值加可重放投影,并使用稳定 Chunk ID、显式版本字段和蓝绿 Collection,因为它能对账、灰度和回滚。亮点必须由重复投递幂等、撤权传播时间、版本零混用和回滚演练证明;代价是增加同步任务、存储副本和发布流程。

9.3 常见错误回答

  • “Milvus 能存十亿向量,所以一定比 pgvector 快”:规模宣称不能代替同条件基准;
  • “插入后调用 flush 就一定立即可查”:混淆持久化、封存、索引、Load 和 Consistency;
  • “HNSW 的 ef 越大越好”:Recall 提高通常伴随延迟和资源代价;
  • “Partition 越多越容易扩展”:高基数分区会制造元数据与调度成本;
  • “Milvus Hybrid Search 已经等于 Reranker”:融合排序不等于 Cross-Encoder 精排;
  • “ACL 在取回结果后过滤即可”:安全边界必须在候选生成前硬限制并二次校验。

9.4 选型停止条件

如果现有 PostgreSQL/Elastic 在目标数据、并发、过滤分布和硬件下已经满足 Recall、P99、QPS、恢复时间与成本,就没有必要仅为技术新颖度引入 Milvus。反之,只有当专用向量负载、独立扩缩、多向量能力或容量收益经基准验证,且团队能承担集群运维时,Milvus 才形成完整选择依据。

10. 面试追问与实践任务

10.1 递进追问

  1. Collection、Partition、Shard、Replica 和 Segment 分别解决什么问题?
  2. 为什么写入成功后仍可能暂时搜索不到?
  3. Growing 与 Sealed Segment 如何共同参与一次查询?
  4. 为什么业务真值不应默认只放在 Milvus?
  5. HNSW、IVF_FLAT、DiskANN 与 FLAT 应怎样建立受控对比?
  6. 如何设计多租户 ACL,并证明不会跨租户召回?
  7. 如何完成 Embedding v1 到 v2 的灰度、回滚与零混用?

10.2 实践任务

  • 用 Docker/Standalone 完成本文最小实验并保存 insert/search 输出;
  • 构造 100 条带两个 tenant 的数据,执行跨租户负向测试;
  • 使用 FLAT 建 Ground Truth,再扫描 HNSW 的 ef
  • 加入 embedding_version 并实现双 Collection Alias 切换;
  • 记录数据规模、维度、过滤比例、并发、Recall@10、P95/P99、QPS、RSS 和索引时间;
  • 再进入生产问题与性能调优完成故障演练。

11. 参考资料

以下均为 Milvus 官方资料,访问日期:2026-07-14:

  1. Milvus Architecture Overview
  2. Main Components
  3. Release Notes
  4. Create Collection
  5. Collection Explained
  6. Consistency
  7. Index Explained
  8. Filtered Search
  9. BM25 Function
  10. Reranking

12. 总结

一句话记忆: Milvus 用流批分离、存算分离和 Segment 生命周期支撑大规模向量检索,但真正可用取决于 Schema、版本、权限、一致性、索引和证据化验证。

  • Milvus 是检索基础设施,不是 Embedding、业务真值库或完整 RAG;
  • 写入、持久化、可见、索引完成和 Load 完成是不同状态;
  • RAG 应保存稳定 ID、租户、ACL、文档和 Embedding 版本;
  • FLAT Ground Truth 与固定 Query 集是 ANN 调优的质量基线;
  • 是否采用 Milvus,要由同条件下的质量、P99、资源和运维成本决定。