返回文章列表
后端架构数据存储会话系统成本优化Agent

会话存储设计:Redis、Postgres 与对象存储怎么选(AI/Agent 场景)

AI 会话数据既包含高频读写的短期状态(流式输出、步骤进度),也包含需要审计与复盘的长期记录(事件日志、工具回执),还可能有大对象(附件、长文本、向量)。本文给出一套可落地的分层存储决策框架:按数据粒度/生命周期/一致性/成本选 Redis、Postgres 或对象存储,并提供冷热分层与迁移策略。

2026年3月4日
Synthly 团队
预计阅读 15 分钟
会话存储分层:Redis、Postgres 与对象存储的冷热数据流转示意图

📷 Photo by JÉSHOOTS via Pexels

先把会话数据拆开:你存的不是“聊天”,是“运行系统”

在 Agent 产品里,“会话”包含至少三类东西:

  1. 交互层数据
  • 用户消息、助手最终回复
  1. 执行层数据
  • run 状态、步骤进度、工具调用回执摘要、重试决策
  1. 审计与运营数据
  • 事件日志、错误分类、成本(token/工具调用)

把它们混在一起存,会让:

  • 查询很难写
  • 热点很难控制
  • 成本很难预测

所以第一步是:按粒度与生命周期分层


一、决策维度:四个问题决定存哪

对每一类数据,问这四个问题:

  1. 访问模式:高频读写还是低频查询?
  2. 一致性:需要强一致吗?允许最终一致吗?
  3. 生命周期:分钟/小时/天/年?需要 TTL 吗?
  4. 查询方式:需要复杂过滤/聚合/索引吗?还是只要按 key 取?

四问答完,通常答案就出来了。


二、三种存储的“正确定位”

1)Redis:短期状态与控制面(热)

适合存:

  • run 状态(running/succeeded/failed)
  • 流式输出缓冲(短期)
  • 幂等键与去重记录(短期)
  • 分布式锁(resource lock)
  • 速率限制计数器

不适合存:

  • 需要审计的长期日志
  • 需要复杂查询的历史数据

一句话:Redis 是“控制面”,不是“事实仓库”。

2)Postgres:事实、审计与查询面(温)

适合存:

  • 会话线程(thread)与消息(message)
  • 事件日志(event log)
  • 工具调用摘要与回执索引
  • 关键指标的聚合表(日报/看板)

优势:

  • 强一致
  • 可索引、可查询
  • 审计与权限好做

3)对象存储:大对象与归档(冷)

适合存:

  • 大段原始文本归档
  • 附件(pdf、图片、音频)
  • 导出的报告文件
  • 大规模评测与离线分析产物

配套建议:

  • 在 Postgres 里存对象元数据与 URL
  • 对象本体放对象存储

三、推荐的分层架构:热/温/冷

把数据按温度分三层,会让系统可扩展且成本可控。

热层(Redis)

  • TTL:分钟~小时
  • 内容:运行时状态、锁、幂等、流式缓冲

温层(Postgres)

  • TTL:天~年(按合规)
  • 内容:消息、事件日志、回执摘要、指标

冷层(对象存储)

  • TTL:按业务与合规
  • 内容:大对象、归档、离线产物

迁移策略:

  • 热 → 温:run 完成后把关键状态落库
  • 温 → 冷:历史归档、压缩存储

四、事件日志表怎么设计:最小可用 schema

你不需要一开始就做复杂的数据湖,但建议至少有一张事件表:

  • event_id
  • thread_id
  • run_id
  • seq
  • event_type
  • payload_summary(可检索摘要)
  • payload_ref(指向对象存储的原始 payload,可选)
  • created_at

关键点:

  • seq 支持重放
  • payload_summary 支持排障与运营分析
  • 原始大 payload 放对象存储,避免数据库膨胀

五、成本模型:为什么“只用 Postgres”也会很贵

很多团队会说:

Postgres 很强,那就全放 Postgres。

问题在于:

  • 事件日志增长极快(每次工具调用、每次 delta 都是事件)
  • 大 payload(长文本/回执)会导致表膨胀
  • 索引维护成本高

所以建议:

  • delta 级别事件不要全落数据库(可聚合/抽样)
  • 只落关键里程碑事件(step/tool/done/error)
  • 大对象走对象存储

六、上线 Checklist(会话存储分层)

  • 数据分层:热(Redis)/温(Postgres)/冷(对象存储)职责明确
  • 运行状态:run 状态可重入(断线重连/后台继续)
  • 事件日志:至少存 step/tool/error/done 里程碑事件
  • 幂等与锁:写操作幂等键、资源锁存 Redis
  • 归档策略:历史数据压缩/迁移/TTL 清理
  • 审计与权限:按 tenant/user 隔离查询,敏感字段脱敏

常见问题

我需要把流式 token delta 存起来吗?

通常不需要全量存。建议存:

  • 最终答案
  • 关键里程碑事件
  • 必要的调试摘要

全量 delta 既贵又难查。

会话历史要支持“重放”,数据应该怎么存?

重放依赖的是事件序列(seq),而不是消息字符串。你可以存“可重放事件”并在前端用 reducer 还原 UI 状态(见前端篇:/articles/chat-frontend-state-from-messages-to-tool-events)。

想看更多工程化文章见 /articles,也可以在 /apps/new 体验 Agent 能力。