跳到正文

Redis 与 AI ​

一句话:Redis 在 AI 链路里首先不是向量库,而是模型外面的低延迟状态层——语义缓存、会话记忆、限流、事件总线;向量检索是 Redis 8 新增的能力,适合中小规模。

适用版本:Redis 8.0+(Query Engine 与 Vector Sets 进入核心),8.2 引入 SVS-VAMANA 索引(以官方文档为准)。

为什么需要 ​

一次 LLM 调用通常几百毫秒到几秒,成本按 token 计。工程上能省的环节几乎都落在 Redis:

  • 语义缓存:相似问题直接返回上次答案,省一次模型调用。
  • 会话记忆:多轮对话的短期上下文、用户画像,要求毫秒级读写和 TTL。
  • 限流:按用户/租户限制模型调用速率,防止打爆配额。
  • 事件总线:Agent 的工具调用、子任务结果用 Stream 传递。
  • 召回层:中小规模的向量相似度检索,作为向量数据库的补充。

这些负载的共同点是「小对象、高并发、可过期」,正好是 Redis 的主场。向量检索只是其中一项,不是 Redis 在 AI 里的全部。

核心机制:访问模式变了 ​

AI 带来的变化不是「多存一种数据类型」,而是访问模式变了:

  • 读远多于写,且 key 是语义的。传统缓存 key 是确定的 ID;语义缓存的 key 是 embedding,命中判断从「相等」变成「相似度超过阈值」。
  • 单 value 变大。一条 1536 维 float32 embedding 约 6 KB,比普通缓存 value 大一个数量级,内存规划要先于功能设计。
  • 写入带生命周期。会话记忆要按用户过期,模型调用配额要按时间窗口重置,事件要被消费组 ACK。
  • 一致性要求分层。缓存答案可以旧几秒;限流计数必须原子;会话记忆不能丢。

这决定了 Redis 的用法:缓存和状态用 String/Hash/List/Stream,向量召回用 Vector Sets 或 Query Engine,限流用 Lua 保证「读-判断-写」原子。

核心机制:两条路线与判定链 ​

两条向量路线 ​

Vector Sets(VADD/VSIM)Query Engine(FT.*)
定位轻量向量集合,API 简单完整检索:向量 + 全文 + 标签/数值过滤
索引HNSWHNSW / FLAT / SVS-VAMANA(8.2+)
过滤元素属性表达式Schema 字段过滤、聚合
适合语义缓存、推荐召回多条件检索、混合检索

Vector Sets 是 Redis 8 的新数据类型,默认 Q8 量化,内存约为 float32 的 1/4;首次 VADD 时确定量化方式(Q8/BIN/NOQUANT),之后不能改。它不是通用向量数据库:一个 Vector Set 本身不跨分片拆分,也没有复杂聚合。Query Engine 才能做「向量 + 标签过滤」的混合检索。

语义缓存的判定链 ​

命中与否只由「相似度阈值 + 是否过期」两个条件决定,未命中必须回写,否则缓存永远不会热起来。

阈值不能拍脑袋:取一批真实问题做离线评测,画「相似度—正确率」曲线,选业务能接受的误答率。阈值过低会把不同问题判成同一个,这是语义缓存最主要的线上事故。缓存的 key 要带模型版本和索引版本,模型升级后能整体失效。

记忆与事件 ​

  • 短期记忆:HSET session:{id} + EXPIRE,或 LPUSH + LTRIM 保留最近 N 轮。
  • 长期记忆:结构化事实存 Hash/JSON,检索走 Query Engine。
  • Agent 事件:XADD 写、XREADGROUP 消费,支持多消费者与 PENDING 重投。
  • 限流:用 Lua 做令牌桶,保证「读计数—判断—写回」原子,不要拆成多条命令。

最小上手 ​

bash
docker run -d --name redis-ai -p 6379:6379 redis:8
redis-cli

Vector Sets(默认 Q8):

VADD docs VALUES 3 0.10 0.20 0.30 doc:1
VADD docs VALUES 3 0.90 0.10 0.10 doc:2
VSIM docs VALUES 3 0.10 0.20 0.31 COUNT 2 WITHSCORES

Query Engine(向量 + 标签过滤):

FT.CREATE idx ON HASH PREFIX 1 chunk: SCHEMA \
  tenant TAG content TEXT \
  embedding VECTOR HNSW 6 TYPE FLOAT32 DIM 3 DISTANCE_METRIC COSINE

HSET chunk:1 tenant t1 content "退款政策" embedding "<binary>"
FT.SEARCH idx "@tenant:{t1}=>[KNN 5 @embedding $vec AS score]" \
  PARAMS 2 vec "<binary>" SORTBY score DIALECT 2

二进制向量的编码容易出错,实际项目用 redis-py/Jedis 等客户端构造,不要手拼。

生产动作 ​

  1. 先算内存再建索引:条数 × 单条向量字节 × 索引放大系数。1536 维 float32 约 6 KB/条,HNSW 经验上再乘 1.5–2;Q8 量化按 1/4 估。算完再决定用不用 Redis。
  2. 显式设置淘汰策略:纯语义缓存用 allkeys-lru;会话记忆和限流计数不能丢,用 noeviction 并监控 used_memory 与写入错误。默认就是 noeviction,写满会直接报错。
  3. 给缓存 key 加版本:sem:{model_version}:{index_version}:{hash}。模型或知识库升级时改版本号即可整体失效,不要靠逐个删 key。
  4. 监控命中率与相似度分布:除了 keyspace_hits/misses,还要抽样记录 top1 相似度。阈值附近请求变多,说明缓存开始大量误判或几乎不命中。
  5. 限流用 Lua 或客户端原子脚本:INCR + EXPIRE 分开写会在两步之间留下没有 TTL 的 key;令牌桶的读-判断-写必须在一次脚本里完成。
  6. 向量数据要可重建:AOF everysec 仍可能丢约 1 秒,索引重建成本又高。原始文本和 embedding 要落在可重放的存储里,Redis 只做检索副本。

边界 ​

  • 内存是唯一硬约束:1536 维 float32 约 6 KB/条;HNSW 图结构经验上再乘 1.5–2 倍,Q8 量化可降到约 1/4。1000 万条就是百 GB 级,先算内存再谈索引。
  • 持久化不是备份:AOF everysec 仍可能丢约 1 秒;向量索引重建成本高,重要数据要能重放。
  • 语义缓存会放大模型错误:缓存的是旧答案,模型或知识更新后要能按版本号整体失效。
  • 不适合当向量主库:没有独立的分片/副本索引管理,内存成本高,持久化弱于数据库。
  • 集群限制:多 key 操作用 hash tag 落到同一 slot;开源 Cluster 下 Query Engine 的分片与能力边界以官方文档为准,规模化检索通常需要 Redis Enterprise/Cloud。
  • maxmemory-policy 要显式配:纯缓存用 allkeys-lru;会话不能丢用 noeviction 并告警——默认就是 noeviction,写满直接报错。
  • 不适合复杂分析:聚合、join、跨租户统计交给 SQL/ES。

选型判断 ​

场景选择
已经在用 Redis,百万级以内,要低延迟、可接受内存成本Redis(Vector Sets 或 Query Engine)
需要向量 + 标签/全文混合过滤,规模中等Redis Query Engine
上千万条、要高压缩比、独立扩缩容、专用索引管理Milvus 等专用向量库
需要强一致、复杂事务、长期归档关系库/专用系统,Redis 只做缓存层

判断标准很简单:如果 AI 只是给现有业务加一个「相似问答」或「会话状态」,Redis 足够;如果向量检索本身是核心业务、数据量持续上亿,就不要把 Redis 当主库。

讲清楚 ​

Redis 在 AI 系统里最重要的角色不是「向量数据库」,而是「模型外面那层低延迟状态」。模型慢且贵,所以要有语义缓存;对话要有记忆;调用要限流;Agent 之间要传事件——这些都在 Redis 里,因为它们是毫秒级、可过期、允许丢的小对象。

Redis 8 把 Query Engine 并进核心,又加了 Vector Sets,所以它确实能存向量、做相似度检索。但要分清两条路线:Vector Sets 简单,适合缓存和召回;Query Engine 才能做向量加标签过滤的混合检索。共同约束是内存——向量很占地方,先算内存再选型。百万级以内、已经在用 Redis,直接用;上千万条或要独立扩缩容,交给 Milvus。

把一门技术讲透到既懂也会用