semantic-router 混合语义缓存(Hybrid Cache)实战:内存 HNSW 热层 + Milvus 持久层架构、配置与监控指南
后端API网关模型推理服务AI Agent【免费下载链接】semantic-routerAn open, programmable decision layer for models and compute.项目地址https://gitcode.com/gh_mirrors/sem/semantic-router点击查看免费下载混合缓存Hybrid Cache是 semantic-router 语义缓存家族中面向生产规模的组合式后端它以进程内 HNSW 索引提供 O(log n) 级别的快速最近邻检索以本地文档缓存承接热数据并以 Milvus 向量数据库作为可扩展、持久化的“单一事实来源”。本文基于仓库中的混合缓存教程与pkg/cache源码实现完整讲解其架构、写入/读取路径、内存管理、YAML 配置、Go API 用法、监控指标与多实例部署方案帮助你为 LLM 网关级联一套既快又稳、重启后可恢复的响应缓存。一、为什么需要混合缓存纯内存与纯向量库的取舍semantic-router 的语义缓存提供多种后端memory、milvus、redis、valkey、qdrant、hybrid它们在“查询速度”与“容量/持久性”之间各有取舍纯内存缓存in-memory延迟最低但条目数受进程内存限制重启即丢失纯 Milvus 缓存可扩展到千万级条目并持久化但每次查询都要走一次分布式向量检索延迟高于本地内存索引。混合缓存backend_type: hybrid的设计目标正是结合两者优势搜索走进程内 HNSW数据全量落在 Milvus热文档再做一层本地缓存。在GetAvailableCacheBackends()的后端能力清单中它的官方描述是Process-local HNSW hot tier backed by shared Milvus storage进程本地 HNSW 热层 共享 Milvus 存储其一致性模型为session并声明Shared共享存储能力参见 cache_factory.go 与 backend_registry.go。二、架构剖析三层结构与职责划分混合缓存的整体架构可用下图概括┌──────────────────────────────────────────────────┐ │ 混合缓存 (Hybrid Cache) │ ├──────────────────────────────────────────────────┤ │ ┌─────────────────┐ ┌──────────────────┐ │ │ │ 内存中的 │ │ 本地缓存 │ │ │ │ HNSW 索引 │◄─────┤ (热数据) │ │ │ └────────┬────────┘ └──────────────────┘ │ │ │ │ │ │ ID 映射 │ │ ▼ │ │ ┌──────────────────────────────────────────┐ │ │ │ Milvus 向量数据库 │ │ │ └──────────────────────────────────────────┘ │ └──────────────────────────────────────────────────┘对应到源码结构体 HybridCache三个核心组件清晰可辨组件源码字段职责进程内 HNSW 索引hnswIndex *HNSWIndex、embeddings [][]float32保存全部条目的嵌入向量用于快速最近邻搜索只占向量空间、不存文档正文ID 映射表idMap map[int]string将 HNSW 内部条目下标Entry index映射到 Milvus 主键 ID检索命中后再回 Milvus 取文档Milvus 向量数据库milvusCache *MilvusCache保存所有完整条目请求体、响应体、查询文本、嵌入、TTL 等作为持久化存储与单一事实来源关键设计点HNSW 索引只保存嵌入向量而不保存文档正文因此即便内存中索引数十万条向量也不会因缓存文档而撑爆内存真正的文档内容全部在 Milvus命中后按 ID 回取。这使混合缓存在“搜索速度”与“百万级条目容量”之间取得了平衡。三、工作原理写入、读取与内存管理3.1 写入路径AddEntry向缓存添加一条完整请求-响应记录时HybridCache.AddEntry 按以下顺序执行生成嵌入使用配置的嵌入模型embedding_model默认mmbert可选qwen3、multimodal对查询文本计算向量写穿到 Milvuswrite-through先持久化完整条目保证数据不因进程崩溃而丢失ttl_seconds 0时直接跳过缓存-1表示使用缓存全局默认 TTL见 milvus_cache.go加入 HNSW 索引在写锁保护下若内存条目已达max_memory_entries上限则先执行一次 FIFO 驱逐evictOneUnsafe再将新向量追加进embeddings、登记idMap最后addNodeHybridOrRebuild将节点接入 HNSW 多层图本地热缓存命中路径后续按需回填详见读取路径。此外还有批量写入接口AddEntriesBatch先批量生成嵌入 → 一次性 Upsert 进 Milvus → 逐个加入 HNSW见 hybrid_cache.go以及面向流式请求的AddPendingRequest/UpdateWithResponse两阶段写入用于“先缓存请求、后补全响应”的场景。3.2 读取路径FindSimilar查询相似条目时HybridCache.FindSimilar 及其底层findSimilar执行生成查询嵌入HNSW 最近邻搜索searchKNNHybridWithThreshold在 HNSW 多层图上从顶层入口点逐层下探使用内积dot product作为相似度度量并支持阈值提前终止hitHybridThreshold见 hybrid_cache_hnsw.go过滤候选只保留相似度 ≥ 阈值默认similarity_threshold: 0.85的候选并通过idMap解析出 Milvus ID本地缓存检查热路径fetchResponseFromCandidates逐个按 ID 回取文档若本地缓存中有匹配文档则立即返回取回时还会做词面极性检查semanticCandidateMatchesPolarity规避“意思相反但向量相近”的误命中Milvus 回退冷路径若 HNSW 候选均不可用例如候选属于其他模型分区、被极性检查拒绝则再调用milvusCache.LookupSimilarWithThreshold做一次带精确 model 过滤的分布式检索——Milvus 持有严格的模型过滤与原始查询校验见 hybrid_cache_lookup.go回填热缓存将取到的文档缓存在本地供后续查询复用。该路径天然区分了两种命中来源hit_milvusHNSW 快速命中并回取成功与冷路径命中未命中则记为miss全部计入统计与指标。3.3 内存管理FIFO 驱逐与延迟重建HNSW 索引受max_memory_entries默认 100,000限制本地文档缓存受local_cache_size默认 1,000限制驱逐策略达到上限后采用FIFO先进先出——evictOneUnsafe直接移除embeddings切片中最老的条目下标 0并整体平移idMap下标见 hybrid_cache.go延迟重建deferred rebuild由于驱逐会使所有下标平移导致 HNSW 图整体失联因此驱逐时仅将图标记为 stalehnswNeedsRebuild true在下次添加时一次性从全部存活向量重建整张图避免“图只剩最后一个节点、缓存降级为近乎 100% 未命中”的经典缺陷addNodeHybridOrRebuild/rebuildHNSWFromEmbeddings见 hybrid_cache.go数据持久性无论内存如何驱逐所有条目始终保留在 Milvus 中内存层只是可再生的加速视图。3.4 启动重建与后台 TTL 回收源码细节补充除了教程中的基本流程当前实现还包含两个值得了解的生产级机制启动时从 Milvus 重建索引NewHybridCache默认调用RebuildFromMilvus(ctx)5 分钟超时把 Milvus 中的全部存活条目回灌进内存 HNSW从而在进程重启后快速恢复热层DisableRebuildOnStartup可关闭该行为不推荐用于生产见 hybrid_cache.go后台 TTL 回收Milvus 会按自身 TTL 静默过期并删除条目但内存索引不会自动感知。实现通过startBackgroundReclaim启动后台协程按 TTL 周期下限 60 秒、单次上限 5 分钟周期性复用RebuildFromMilvus重查 Milvus让索引始终跟踪“存活工作集”而非历史峰值水位见 hybrid_cache_reclaim.go。四、配置指南从全局后端到决策级插件4.1 基础配置混合缓存的全局配置挂在semantic_cache配置块下源码中该块对应SemanticCache/ResponseCacheStoreConfig见 runtime_config.go 与 config.gosemantic_cache: enabled: true backend_type: hybrid similarity_threshold: 0.85 ttl_seconds: 3600 # 混合缓存特定设置 max_memory_entries: 100000 # HNSW 中的最大条目数 local_cache_size: 1000 # 本地文档缓存大小 # HNSW 参数 hnsw_m: 16 hnsw_ef_construction: 200 # Milvus 配置 backend_config_path: config/semantic-cache/milvus.yaml几点由源码确认的配置语义similarity_threshold必须是0.0 ~ 1.0之间的浮点数ttl_seconds不得为负否则ValidateCacheConfig直接返回错误见 cache_factory.gohybrid后端必须提供 Milvus 配置否则校验失败“milvus configuration is required for hybrid cache backend”见 backend_registry.go同时不能同时配置其他后端redis/valkey/qdrant的专属配置未显式配置时NewHybridCache会套用默认值MaxMemoryEntries 100000、HNSWM 16、HNSWEfConstruction 200见 hybrid_cache.go若使用milvus配置结构体而非文件路径则直接内联milvus:子块即可backend_config_pathMilvusConfigPath在源码中已被标记为Deprecated推荐优先内联或使用新式Milvus *config.MilvusConfig字段见 hybrid_cache.go。4.2 决策级配置基于插件混合缓存不仅可以在全局开启还可以作为决策插件plugin绑定到特定路由规则上实现“不同域不同缓存策略”。插件类型注册名为semantic-cache常量DecisionPluginSemanticCache见 routing_surface_catalog.go其决策级配置示例为signals: domains: - name: math description: 数学查询 mmlu_categories: [math] decisions: - name: math_route description: 路由数学查询并使用严格缓存 priority: 100 rules: operator: AND conditions: - type: domain name: math modelRefs: - model: openai/gpt-oss-120b use_reasoning: true plugins: - type: semantic-cache configuration: enabled: true similarity_threshold: 0.95 # 对数学准确性要求非常严格该配置的含义是当请求命中math域且满足 AND 条件时路由到openai/gpt-oss-120b模型同时挂载语义缓存插件并把该决策的缓存相似度阈值收紧到0.95——比全局的0.85更严格从而在数学这类对准确性敏感的领域宁可多命中大模型推理也不轻易复用缓存结果。决策级配置允许在configuration内覆盖enabled、similarity_threshold等缓存参数实现按路由粒度的差异化缓存策略。4.3 配置参数总表参数类型默认值描述backend_typestring-必须为hybridenabledbooltrue全局默认是否启用语义缓存similarity_thresholdfloat0.85缓存命中的最小相似度合法区间 0.0–1.0ttl_secondsint3600缓存条目过期时间0 表示不缓存-1 表示使用全局默认源码确认max_entriesint-内存后端条数上限hybrid 后端使用max_memory_entriesmax_memory_entriesint100000HNSW 索引中的最大条目数local_cache_sizeint1000热文档缓存大小hnsw_mint16HNSW 双向链路数每节点每层最大邻居数hnsw_ef_constructionint200HNSW 构建质量构建期候选动态列表大小embedding_modelstringmmbert嵌入模型可选mmbert/qwen3/multimodal见 cache_interface.gobackend_config_pathstring-Milvus 配置文件路径已标记 Deprecated见 hybrid_cache.go注全局默认后端实际为memoryenabled: true、similarity_threshold: 0.8、max_entries: 1000、ttl_seconds: 3600、eviction_policy: fifo见 cache_factory.go 与 canonical_defaults.go。要启用混合缓存请显式设置backend_type: hybrid。4.4 Milvus 配置详解创建 Milvus 配置文件教程示例milvus: address: localhost:19530 collection_name: semantic_cache dimension: 384 index_type: HNSW metric_type: IP params: M: 16 efConstruction: 200仓库中提供了更完整的真实配置样例其结构与config.MilvusConfig严格对应见 runtime_config.goconnection: host: localhost port: 19530 database: semantic_router_cache timeout: 30 auth: enabled: false username: password: tls: enabled: false cert_file: key_file: ca_file: collection: name: semantic_cache description: Semantic cache for LLM request-response pairs vector_field: name: embedding dimension: 0 # 0 表示采用嵌入模型原生维度Vela Embedding 可选 768/512/256/128/64 metric_type: IP # 可选 IP / COSINE / L2未识别值会告警并直接按相似度比较 index: type: HNSW params: M: 16 efConstruction: 64 search: params: ef: 64 topk: 10 consistency_level: Session # 可选 Strong / Session / Bounded / Eventually logging: level: info development: drop_collection_on_startup: true # 开发模式启动即清空集合 auto_create_collection: true # 集合不存在时自动创建配套的源码行为值得注意dimension: 0时resolveCacheDimension会自动采用已准备嵌入模型的原生输出维度并在createCollection时写入真实维度见 milvus_cache.go 与 milvus_cache.gometric_type会在初始化时被归一化仅接受IP/COSINE/L2其他值记录告警见 milvus_cache.gocreateCollection自动创建含id主键、request_id、model、query、request_body、response_body、embeddingFloatVector、timestamp、ttl_seconds、expires_at字段的集合 schema并基于metric_type、M、efConstruction创建 HNSW 索引见 milvus_cache.go构建需启用 Milvus 支持配置文件注释明确要求使用go build -tagsmilvus编译且hybrid_cache.go、hybrid_cache_hnsw.go等文件带有//go:build !windows构建约束Windows 下会退化为 stub 实现见 hybrid_cache_stub.go。五、Go 使用示例初始化混合缓存并执行写入、查询与统计的完整示例API 与HybridCacheOptions字段一一对应见 hybrid_cache.goimport github.com/vllm-project/semantic-router/src/semantic-router/pkg/cache // 初始化混合缓存 options : cache.HybridCacheOptions{ Enabled: true, SimilarityThreshold: 0.85, TTLSeconds: 3600, MaxMemoryEntries: 100000, HNSWM: 16, HNSWEfConstruction: 200, MilvusConfigPath: config/semantic-cache/milvus.yaml, LocalCacheSize: 1000, } hybridCache, err : cache.NewHybridCache(options) if err ! nil { log.Fatalf(创建混合缓存失败: %v, err) } defer hybridCache.Close() // 添加缓存条目 err hybridCache.AddEntry( request-id-123, gpt-4, 什么是量子计算, []byte({prompt: 什么是量子计算}), []byte({response: 量子计算是...}), ) // 搜索相似查询使用全局阈值 response, found, err : hybridCache.FindSimilar( gpt-4, 解释量子计算机, ) if found { fmt.Printf(缓存命中响应: %s\n, string(response)) } // 搜索相似查询自定义阈值 response, found, err hybridCache.FindSimilarWithThreshold( gpt-4, 解释量子计算机, 0.9, ) // 获取统计信息 stats : hybridCache.GetStats() fmt.Printf(HNSW 中的总条目数: %d\n, stats.TotalEntries) fmt.Printf(命中率: %.2f%%\n, stats.HitRatio * 100)除教程展示的方法外HybridCache还完整实现了CacheBackend接口见 cache_interface.go常用方法还包括LookupSimilarWithThreshold(ctx, model, query, threshold) (LookupResult, error)返回响应体与相似度、时间戳等元数据并支持上下文取消ctx取消会作为错误返回而非未命中AddEntriesBatch(entries []CacheEntry) error批量写入适合冷启动灌数据AddPendingRequest/UpdateWithResponse两阶段写入配合流式场景Flush()强制 Milvus 落盘CheckConnection(ctx)健康检查实际代理到 Milvus 连接检查Close()停止后台回收协程、关闭 Milvus 连接并清空内存结构见 hybrid_cache.go。六、监控与指标GetStats()返回的CacheStats见 cache_interface.go包含以下可用字段stats : hybridCache.GetStats() // 可用指标 stats.TotalEntries // HNSW 索引中的条目数 stats.HitCount // 总缓存命中次数 stats.MissCount // 总缓存未命中次数 stats.HitRatio // 命中率 (0.0 - 1.0)教程给出的 Prometheus 指标示意标签形式沿用文档# HNSW 中的缓存条目数 semantic_cache_entries{backendhybrid} # 缓存操作 semantic_cache_operations_total{backendhybrid,operationfind_similar,statushit_local} semantic_cache_operations_total{backendhybrid,operationfind_similar,statushit_milvus} semantic_cache_operations_total{backendhybrid,operationfind_similar,statusmiss} # 缓存命中率 semantic_cache_hit_ratio{backendhybrid}需要说明的是当前仓库实际的指标实现位于 cache_metrics.go度量名以llm_cache_前缀注册语义与上表一一对应llm_cache_operations_total{backend, operation, status}操作计数status 取值包括hit_milvus、miss、error、success等hit_local由本地热缓存路径承载见 hybrid_cache_lookup.gollm_cache_entries_total{backend}当前条目数 GaugeUpdateCacheEntries(hybrid, n)llm_cache_operation_duration_seconds{backend, operation}操作耗时直方图分桶 1ms–10sllm_cache_plugin_hits_total/llm_cache_plugin_misses_total{decision_name, plugin_type}决策级插件的命中/未命中计数与上文的semantic-cache插件配套。在 Grafana 面板中可用rate(llm_cache_operations_total{backendhybrid,statushit_milvus}[5m])与rate(llm_cache_operations_total{backendhybrid,statusmiss}[5m])计算混合缓存的实时命中率。七、多实例部署混合缓存天然支持多实例水平扩展每个实例维护自己独立的进程内 HNSW 索引与本地热缓存但共享同一个 Milvus 实例以此实现持久化与数据一致性┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ 实例 1 │ │ 实例 2 │ │ 实例 3 │ │ HNSW 缓存 │ │ HNSW 缓存 │ │ HNSW 缓存 │ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │ │ │ └─────────────────┼─────────────────┘ │ ┌──────▼──────┐ │ Milvus │ │ (共享) │ └─────────────┘该部署模式与源码的能力声明一致GetAvailableCacheBackends()将 hybrid 描述为进程本地热层 共享持久层见 cache_factory.go其Shared: true能力位表示存储可跨实例共享见 backend_registry.go。多实例部署的要点每个实例启动时都会RebuildFromMilvus重建自己的内存索引因此新增实例 / 实例重启后热层会在启动阶段快速恢复实例间的缓存一致性由 Milvus 承担共享写入源单实例的内存 HNSW 只是各自的加速副本后台 TTL 回收保证各实例索引跟随 Milvus 的过期进度不会长期保留已过期条目的“幽灵向量”。八、源码级验证驱逐与索引一致性的回归测试混合缓存的 FIFO 驱逐与延迟重建机制有专门的回归测试背书hybrid_cache_eviction_test.go 验证了以下不变量驱逐后图与向量集保持同步TestHybridCacheEvictionRebuildsHNSWIndex以maxEntries 5灌入 20 条 one-hot 向量断言驱逐后HNSW 节点数 存活向量数且每个保留条目都能通过searchKNNHybridWithThreshold检索到该测试注释明确说明这是对“驱逐后 HNSW 图只剩最后一个节点、缓存降级为 ~100% 未命中”缺陷的回归防护延迟重建握手TestHybridCacheDeferredRebuildMechanics固定了“驱逐置hnswNeedsRebuild并清空图 → 下次添加时从全部 embeddings 重建并清除标记”的状态机行为。这两组测试从工程上确认即便达到内存上限触发 FIFO 驱逐混合缓存的索引一致性与命中率也不会劣化——驱逐只影响热层容量Milvus 中的数据永不丢失。九、另请参阅内存缓存In-Memory Cache纯进程内存的轻量语义缓存后端适合单机小规模场景Milvus 缓存纯 Milvus 后端的分布式语义缓存是混合缓存的持久层基础核心实现hybrid_cache.go、hybrid_cache_hnsw.go、hybrid_cache_lookup.go配置结构runtime_config.go、Milvus 配置样例指标实现cache_metrics.go赞分享后端API网关模型推理服务AI Agent【免费下载链接】semantic-routerAn open, programmable decision layer for models and compute.项目地址https://gitcode.com/gh_mirrors/sem/semantic-router点击查看免费下载相关推荐Semantic Router 集成 Milvus 语义缓存持久化向量后端配置与部署实战Semantic Router 集成 Milvus 语义缓存持久化向量后端配置与部署实战 本文围绕 Semantic Router 仓库 v0.2 文档中的后端API网关模型推理服务AI AgentSemantic Router 集成 Milvus 向量库持久响应缓存部署与配置完全指南Semantic Router 集成 Milvus 向量库持久响应缓存部署与配置完全指南 导读 本指南讲解如何在 Semantic Router 中把 Mil后端API网关模型推理服务AI AgentSemantic Router 部署 Milvus 语义缓存后端Kubernetes 全流程实战指南Semantic Router 部署 Milvus 语义缓存后端Kubernetes 全流程实战指南 本指南以 Semantic Router 仓库中的 Mi后端API网关模型推理服务AI Agent上一篇如何用「daily-check-in」打造你的专属打卡神器超简单微信小程序开发指南下一篇大麦网自动抢票终极指南三步告别手速焦虑技术锁定热门演出门票创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考