多用户 Agent 系统: 部署在 K8s 上, 用户之间如何共享记忆与知识
先把问题拆开: "共享记忆"不是一件事
一个 Agent 系统里的"记忆"至少有四层, 共享范围各不一样, 混在一起设计必出问题:
层 |
内容 |
共享范围 |
例子 |
|---|---|---|---|
会话记忆 |
当前对话的上下文 |
单次会话私有 |
"上一轮你说过用 Postgres" |
用户记忆 |
这个用户的偏好、历史 |
用户私有, 跨会话 |
"我喜欢简洁的回答" |
租户/团队记忆 |
团队沉淀的经验 |
租户内共享 |
"我们团队的代码规范是..." |
全局知识 |
所有用户共用的知识库 |
全员共享 |
产品文档、FAQ、最佳实践 |
所以"用户之间共享记忆"在工程上真正的问题是: 怎么让多个用户的 Agent 实例读写同一批知识, 同时又不把彼此的私有数据泄露出去。 在 K8s 上, 这个问题具体化为: 记忆存哪、Agent 实例怎么访问、怎么隔离、怎么保持一致性。
下面按常见方案展开, 最后给选型表。
方案总览
方案 |
记忆存哪 |
Agent 怎么访问 |
适合场景 |
主要缺点 |
|---|---|---|---|---|
一、共享文件卷 |
RWX PVC (NFS/cephfs) 或对象存储 |
直接挂盘读文件 |
小团队、知识是文档文件 |
无语义检索, 无权限粒度 |
二、共享向量库 |
向量数据库独立部署 |
SDK / HTTP 检索 |
RAG 知识共享, 最主流 |
需要自己设计隔离模型 |
三、集中式记忆服务 |
自建 Memory Service (Postgres/Redis 后端) |
REST/gRPC API |
结构化记忆 + 细粒度权限 |
要自研, 有维护成本 |
四、MCP 记忆服务器 |
MCP Server 作为共享服务 |
Agent 通过 MCP 协议调用 |
已用 MCP 生态的系统 |
协议偏工具调用, 大批量检索不经济 |
五、消息队列同步 |
Kafka 等, 各实例本地存副本 |
事件发布/订阅 |
多实例最终一致的记忆广播 |
一致性复杂, 有延迟 |
六、知识图谱 |
Neo4j 等图数据库 |
Cypher 查询 |
实体关系型知识 |
建设与维护成本最高 |
实际系统几乎都是组合使用: 全局知识走向量库, 用户偏好走记忆服务, 热数据走 Redis, 互不矛盾。
方案一: 共享文件卷 —— 最简单直接
思路: 把知识文档放进一个 ReadWriteMany 的 PersistentVolume(NFS、cephfs、JuiceFS 都行), 所有 Agent Pod 挂载同一个卷; 或者直接放对象存储(MinIO/S3), 启动时同步。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: shared-knowledge
spec:
accessModes: ["ReadWriteMany"]
storageClassName: cephfs
resources:
requests:
storage: 20Gi
---
# Agent Pod 中:
volumeMounts:
- name: knowledge
mountPath: /knowledge # 所有用户实例看到同一份文档
readOnly: true # 共享知识建议只读
要点:
共享知识挂只读, 写入走单独的发布流程(一个 Job 或管理端写卷), 避免用户实例互相覆盖;
优点是零开发量, 缺点同样明显: 没有语义检索、没有权限粒度(要么全看到要么看不到)、大目录读取慢;
适合: 知识就是一批 Markdown/PDF 文档, 团队规模小, 先跑起来再说。
方案二: 共享向量库 —— 当前最主流
思路: 向量数据库(Qdrant / Milvus / Weaviate / pgvector)作为独立服务部署在集群里, 所有 Agent 实例通过网络访问, 用集合(collection)划分 + 元数据过滤实现"共享与隔离并存"。
K8s 上的典型部署:
┌─────────────────────────────────────────────────────┐
│ namespace: ai-platform │
│ │
│ agent-deployment (多副本, 服务多用户) │
│ │ │
│ ▼ HTTP/gRPC │
│ qdrant (StatefulSet + PVC) │
│ ├── collection: global_kb ← 全员共享 │
│ ├── collection: tenant_a_kb ← 租户 A 共享 │
│ └── collection: tenant_b_kb ← 租户 B 共享 │
│ │
│ embedding-service (Deployment) │
└─────────────────────────────────────────────────────┘
隔离的三种做法, 粒度从粗到细:
做法 |
实现 |
适用 |
|---|---|---|
按集合隔离 |
每个租户一个 collection, 全局知识单独一个 collection |
租户少而固定 |
按元数据过滤 |
单一大集合, 每条向量带 |
租户多、动态创建 |
混合 |
全局知识一个集合 + 用户/租户记忆用元数据过滤 |
最常见 |
检索时把"该用户能看到的所有范围"拼进 filter:
# 一次检索同时命中全局知识和本租户知识
results = vector_db.search(
query_embedding=embed(question),
filter={
"should": [
{"key": "scope", "match": "global"},
{"key": "scope", "match": f"tenant:{tenant_id}"},
{"key": "scope", "match": f"user:{user_id}"},
]
},
top_k=8,
)
要点:
写入路径要管起来: 谁都能往全局知识写, 知识库很快就变成垃圾场。常见做法是用户写入先进"待审核区", 管理员或另一个审核 Agent 确认后才提升为全局可见;
embedding 服务也部署在集群内, 避免每个 Agent Pod 各自加载模型浪费内存;
pgvector 可以直接复用已有的 Postgres, 数据量不大(百万级向量以内)时比单独养一个 Milvus 省心得多。
方案三: 集中式记忆服务(Memory-as-a-Service)
思路: 把"记忆"做成一个独立的微服务, 提供 remember / recall / forget API, 后端用 Postgres(结构化记忆) + Redis(热数据、会话状态)。所有 Agent 实例无状态, 记忆全部收口到这一个服务, 权限、审计、TTL 都在这一层做。
┌────────────┐ ┌────────────┐ ┌────────────┐
│ Agent Pod │ │ Agent Pod │ │ Agent Pod │ 用户 A / B / C
└─────┬──────┘ └─────┬──────┘ └─────┬──────┘
└────────────────┼────────────────┘
▼ REST/gRPC
┌─────────────────┐
│ memory-service │ ← 唯一写入口, 鉴权/审计/去重/合并
│ (Deployment) │
└────────┬────────┘
┌──────────┼──────────┐
▼ ▼ ▼
Postgres Redis Qdrant
(事实/偏好) (会话热数据) (语义记忆)
API 形状大致是:
POST /memories {user_id, scope, content, ttl}
GET /memories/recall ?user_id=..&query=..&scopes=user,tenant,global
DELETE /memories/{id} ← 支持"被遗忘权", 合规需要
相比"Agent 直连数据库"的优势:
权限收口: Agent Pod 拿不到数据库凭据, 只能带着用户身份调 API, 服务层校验
scope, 用户 A 永远读不到用户 B 的私有记忆;写入治理: 去重(相似记忆合并)、冲突处理(新事实覆盖旧事实)、审计日志, 都有地方放;
Agent 无状态化: Agent Deployment 可以随意扩缩容、滚动更新, 记忆不丢。这是 K8s 上最舒服的一点 —— Pod 就是耗材, 状态全在外面。
开源世界里 Mem0、Zep 这类项目干的就是这件事, 可以直接部署在集群里当这个服务用, 也可以按它的思路自研。
方案四: MCP 共享记忆服务器
思路: 如果系统已经基于 MCP 搭工具生态(见 MCP: AI 应用的"USB-C"接口), 那么"共享记忆"可以就是一个 MCP Server, 对外暴露 search_knowledge / save_memory 之类的工具。
在 K8s 上把它部署成集群内的常驻服务:
apiVersion: apps/v1
kind: Deployment
metadata:
name: memory-mcp-server
spec:
replicas: 2
template:
spec:
containers:
- name: server
image: your-org/memory-mcp:latest
env:
- name: DATABASE_URL
valueFrom: { secretKeyRef: { name: memory-db, key: url } }
各 Agent 以 streamable HTTP 方式连接这个 MCP Server。好处是协议标准化: 不同框架写的 Agent(LangChain 的、自研的)都能用同一份记忆, 换 Agent 框架不用改记忆层。代价是每次记忆读写都是一次工具调用, 高频大批量检索不如直接 SDK 连库经济 —— 所以它适合"低频、需要模型自己决定何时存取"的记忆, 不适合每轮对话都跑的热路径。
方案五: 消息队列同步 —— 多实例最终一致
思路: 每个 Agent 实例(或每个用户分片)持有本地记忆副本保证低延迟, 写入时发事件到 Kafka, 其他实例订阅后更新自己的副本:
Agent-1 写入记忆 ──► Kafka topic: memory-events
├──► Agent-2 消费, 更新本地缓存
├──► Agent-3 消费, 更新本地缓存
└──► 归档消费者, 落 Postgres
适用面其实比较窄: 只有当你有大量有状态实例(比如每个用户一个常驻 Agent Pod, 用 StatefulSet 部署)且读延迟敏感时才值得。大多数情况下方案三(集中服务)更简单。如果用了, 必须处理好:
事件顺序(按
user_id分区, 保证同一用户的记忆事件有序);失败重放(消费者挂了, 重启后从 offset 继续);
"刚写完立刻读"的读己之写一致性(写后同步查一次源, 或者写的时候同步更新本地)。
方案六: 知识图谱 —— 实体关系型共享知识
当共享知识不是"一堆文档段落"而是"实体和关系"("服务 X 依赖服务 Y"、"这个 bug 的负责人是张三")时, 向量检索力不从心, 用图数据库(Neo4j / NebulaGraph)作为共享记忆底座。各 Agent 查询时沿着关系遍历, 天然适合组织级的知识沉淀。
成本最高的方案: 实体抽取、关系维护、图谱清洗都是活。一般作为向量库的补充而不是替代 —— 向量库管"语义相似", 图谱管"精确关系"。
K8s 部署形态的选择
不管选哪个方案, 都要回答"记忆组件以什么形态跑在集群里":
形态 |
做法 |
适合 |
|---|---|---|
独立服务 |
记忆服务/向量库做成独立 Deployment/StatefulSet + Service, Agent 通过 ClusterIP 访问 |
绝大多数情况。无状态 Agent + 有状态记忆分离, 扩缩容互不干扰 |
Sidecar |
每个 Agent Pod 里跑一个记忆容器 |
几乎不推荐用于"共享"场景: sidecar 天生是 per-Pod 的, 和共享矛盾; 只适合本地缓存层 |
DaemonSet |
每个节点一个记忆代理 |
极端低延迟本地缓存, 配合方案五的副本同步 |
Operator 管理 |
用 Operator 管理向量库/图数据库的生命周期(备份、扩缩容) |
生产环境, 有状态组件多的时候 |
两条经验:
Agent 无状态, 记忆外置。这是 K8s 上的金科玉律, 也是"能共享"的前提 —— 记忆在 Pod 里, Pod 一重启就没了, 更谈不上共享;
有状态组件用 StatefulSet + PVC, 并且备份策略从第一天就要有。记忆丢失比代码故障更难恢复。
共享的三个坑: 隔离、一致性、治理
隔离: 共享的反面是泄露
所有记忆条目必须带
tenant_id/user_id/scope, 检索侧强制过滤, 不能依赖调用方自觉传 filter —— 在记忆服务层默认追加当前身份的范围;向量库层如果用 K8s NetworkPolicy 限制只有记忆服务能连向量库, 就堵死了"绕过 API 直连库"的口子;
删除权: 用户要求删除自己的记忆时要能删干净(向量库、关系库、备份里), 合规场景这是硬需求。
一致性: 两个人同时写入怎么办
用户 A 说"数据库密码是 X", 用户 B 说"是 Y", 全局知识里信谁? 常见做法: 写入带版本号和时间戳, 新覆盖旧但保留历史; 冲突条目标记为
contested, 召回时如实告诉模型"有两种说法";写全局知识走审核流(方案二里说的待审核区), 是防止知识污染最有效的单一手段。
治理: 记忆会腐烂
TTL: 会话记忆小时级, 用户偏好月级且每次命中自动续期, 全局知识定期人工/模型复审;
去重合并: 相似度极高的记忆合并, 否则召回结果全是重复内容挤占上下文;
可观测: 记录每条记忆的命中率, 长期零命中的就是该清理的; 记录谁在什么时候写了什么, 出问题能追溯。
选型建议
你的情况 |
建议 |
|---|---|
先把功能跑起来, 团队 < 20 人 |
方案一(共享卷) + 方案二(pgvector 单集合), 一周能上线 |
标准 SaaS 多租户, 需要可靠隔离 |
方案三(记忆服务) + 方案二(向量库元数据过滤), Agent 无状态化 |
已重度使用 MCP 生态 |
在方案三外面包一层方案四的 MCP Server |
每用户一个常驻实例, 读延迟敏感 |
方案五(事件同步)叠加本地缓存 |
知识是强关系型(依赖、负责人、拓扑) |
方案二之上补方案六的图谱 |
一条通用结论: 共享走"集中式服务 + 范围标签", 私有走"强制过滤", 写入走"审核流", 这三句话覆盖了 90% 的多用户 Agent 记忆设计。
参考资料
Mem0 —— 开源的 Agent 记忆层, 方案三的典型实现
Zep —— 另一条记忆服务路线, 时序知识图谱驱动
Qdrant Multitenancy —— 向量库多租户隔离的官方做法
Model Context Protocol —— 方案四的协议基础