当前位置:首页 > 文章列表 > 科技周边 > 人工智能 > 向量数据库按租户过滤时怎样避免召回范围串租户

向量数据库按租户过滤时怎样避免召回范围串租户

来源:17golang原创 2026-09-07 08:22:00 0浏览 收藏

向量相似度只回答“内容像不像”,不会回答“这个结果是否属于当前租户”。多租户 RAG 或知识库如果把所有数据放进同一个 collection,却只依赖 query vector 排序,召回范围就可能跨过租户边界。

可靠做法是把 tenant_id 当成服务端鉴权后的必选查询条件:写入每条向量记录,按精确字符串建立过滤索引,并把它与向量查询用 AND 关系合并。租户数量、隔离要求或跨租户分析再决定是否使用 namespace、partition key 或独立 collection。
要点速览
  • tenant_id 必须来自已验证的请求上下文,不能信任客户端参数。
  • 共享集合方案要同时保证“入库有字段”和“查询必过滤”,缺一都会留下串租户窗口。
  • 过滤后的候选范围、topK、审计日志和跨租户回归用例要一起纳入上线检查。

先把租户身份变成不可绕过的查询条件

最容易被忽略的地方不是向量库,而是查询服务的边界。请求体里带来的 tenant_id 只能作为业务参数,不能直接决定权限。服务应先从已验证的 API key、JWT 或会话映射出当前租户,再把这个值传给检索函数;没有租户身份时直接拒绝查询。

入库也要遵循同一个原则。每条记录至少保留 tenant_iddoc_id 和可用于展示的标题。tenant_id 使用稳定的内部标识,避免把可变的公司名称或用户昵称当作隔离键。

向量数据库多租户检索中鉴权上下文、租户查询条件、keyword 索引与向量集合的边界关系
图1:请求身份经过鉴权上下文进入租户查询条件,再与 keyword 索引和向量集合形成静态隔离边界。

共享集合的过滤写法要和向量查询绑定

下面用 Qdrant Python 客户端表达一条共享集合查询。Qdrant 把附加字段称为 payload,精确字符串适合使用 keyword 类型;过滤条件放在查询对象中,表示只在符合租户条件的记录里做相似度检索。

from qdrant_client import QdrantClient, models

def search_for_tenant(client: QdrantClient, collection: str,
                      verified_tenant_id: str, query_vector: list[float]):
    # tenant_id 必须来自已验证的鉴权上下文,不能取请求体原值
    if not verified_tenant_id:
        raise ValueError("missing tenant identity")

    return client.query_points(
        collection_name=collection,
        query=query_vector,
        query_filter=models.Filter(
            must=[
                models.FieldCondition(
                    key="tenant_id",
                    match=models.MatchValue(value=verified_tenant_id),
                )
            ]
        ),
        limit=5,
        with_payload=["tenant_id", "doc_id", "title"],
    ).points

这个函数的重点不是 SDK 方法名,而是调用契约:检索函数只接收已经验证的租户身份,过滤条件不能由上层可选地拼接。若业务确实需要跨租户分析,应单独暴露受权限控制的接口,明确传入允许的租户集合,而不是复用单租户搜索接口。

生产数据还应为 tenant_id 建立精确过滤索引,并在写入流程中拒绝缺字段记录。索引解决的是过滤效率,不能替代权限判断;权限服务解决的是“谁能查”,过滤条件解决的是“库里只返回哪一组”。

为什么只在召回后过滤仍然不够

有些实现先从全库取 topK,再在应用层筛掉其他租户。这样既扩大了敏感数据进入应用进程的范围,也会让过滤后的结果数量不可控:全库 topK 中如果恰好没有当前租户文档,应用层只能得到空结果,不能把它当成完整的租户内 topK。

正确边界是让向量库收到带 tenant 条件的查询,随后再在返回对象中复查 tenant_id 与请求上下文是否一致。这个复查是纵深防御,不应成为唯一隔离措施。测试时至少准备两个租户的相同问题文档,并验证 A 的向量查询不会返回 B 的 doc_id

方案适合场景主要代价
共享集合 + payload filter大量小租户、结构相同每条记录和每次查询都必须守住字段约束
namespace / partition key租户边界稳定,想缩小搜索范围依赖具体向量库语义,跨租户查询要单独设计
独立 collection少量大租户或更强物理隔离集合数量、索引、迁移和运维成本上升

按隔离强度和租户规模选择存储边界

Qdrant 的多租户文档把共享 collection 的 payload 分区、用户自定义分片和组合方式列为不同取舍;Milvus 也提供 database、collection、partition 和 partition key 等层级。它们的名字不能直接互换,落地前要确认目标引擎的过滤、分区、RBAC 和跨租户查询语义。

如果租户多而数据量相近,共享集合配合精确索引通常更容易运营;如果单个大租户需要独立资源或要降低 noisy neighbor 风险,可以提升到专用 shard、partition 或独立 collection。合规要求、删除范围、备份恢复和租户级限流往往比一次查询的延迟更能决定方案。

无论选择哪一层,应用接口都应保留统一的“当前租户”概念。namespace 或 partition 只是存储路由,不应让前端自由填写并直接切换;路由值仍需由服务端根据授权结果生成。

共享向量集合、metadata filter、partition key 与独立 collection 的多租户隔离策略关系
图2:共享集合过滤、分区键和独立集合分别对应不同的逻辑与物理边界,选择时同时看隔离和运营成本。

上线前用四组用例抓住串租户窗口

第一组是正常隔离:A、B 各写入相同语义但不同 doc_id 的文档,A 查询时断言所有结果的 tenant_id 都是 A。第二组是越权输入:把请求体中的 tenant_id 改成 B,结果仍应由鉴权上下文决定,而不是切到 B。

第三组检查脏数据:缺少 tenant_id、空字符串、大小写不一致或错误类型的记录不能静默进入正式集合。第四组检查接口契约:没有租户身份、过滤条件被移除、跨租户列表超出授权范围时,都应得到明确错误并写入审计日志。

监控上不要只看总召回量,还要记录租户过滤后的候选量、最终命中文档的租户一致性、空结果比例和按租户的延迟。过滤后候选长期过少时,优先检查数据写入与 embedding 分片,而不是先把 topK 无限调大。

常见问题

只给向量加 tenant_id,不建立索引可以吗?

逻辑上可以表达过滤,但大规模查询可能承担更高过滤成本;具体是否强制索引取决于引擎的 strict mode 和部署配置。把索引当性能基础设施,同时保留鉴权和回归测试。

namespace 能否替代权限校验?

不能。namespace、partition 或 collection 是存储和查询范围,不能证明调用者有权访问该范围。范围标识必须由服务端根据身份生成。

为什么过滤后结果数量经常不足?

可能是当前租户有效数据少、字段缺失、过滤值类型不一致,或全库 topK 后置过滤造成的。先检查入库字段和查询边界,再考虑调整租户内 topK。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Go HTTP Header 写入后再修改为什么客户端看不到Go HTTP Header 写入后再修改为什么客户端看不到
上一篇
Go HTTP Header 写入后再修改为什么客户端看不到
Go strings.Builder 怎么拼接大量片段并避免无效转换
下一篇
Go strings.Builder 怎么拼接大量片段并避免无效转换
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • SuperCLUE中文大模型评测基准:功能、能力维度与应用指南
    SuperCLUE
    SuperCLUE是权威的中文大语言模型综合评测基准,涵盖语言理解、知识应用、AI Agent智能体及安全性等12项核心能力。通过多轮对话与客观测试,定期发布榜单与技术报告,为模型研发、优化及行业选型提供科学依据。
    171次使用
  • C-Eval中文评测基准:大语言模型多学科能力评估指南
    C-Eval
    深入了解C-Eval中文评估套件,涵盖52个学科与4级难度。本文详解其功能特点、Zero-shot/Few-shot使用方法及代码示例,助您全面评测LLM中文理解与泛化能力。
    101次使用
  • AI Prompt Library:免费AI提示词库,助力ChatGPT高效创作与营销
    AI Prompt Library
    探索AI Prompt Library免费资源库,涵盖营销、写作及多场景AI提示词。兼容ChatGPT、Claude等工具,一键复制优化输出,提升工作效率。
    20次使用
  • LangGPT提示词框架:结构化Prompt设计方法与开源工具指南
    LangGPT
    LangGPT是一种受编程语言启发的结构化提示词设计工具,提供双层框架、模块化模板及变量功能,帮助用户高效编写高质量Prompt。该项目已在GitHub免费开源,适用于内容创作、编程辅助等多场景。
    32次使用
  • ClickPrompt:AI提示词生成与优化工具,支持Stable Diffusion、ChatGPT及代码辅助
    ClickPrompt
    ClickPrompt是一款专为AI提示词编写者设计的开源在线工具,支持Stable Diffusion绘图、ChatGPT对话及GitHub Copilot代码辅助。提供Prompt自动生成、一键运行、社区分享及可视化优化功能,帮助用户高效获取精准AI输出。
    71次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码