Redis 8.4 之后,缓存和检索引擎的边界已经消失
Redis 8.4 之后,缓存和检索引擎的边界已经消失
先给一个可能让你不舒服的结论:把向量检索塞进 Redis,2026 年真正的风险已经不是「性能够不够」,而是「你以为它解决了延迟问题,其实它主要解决的是运维拓扑问题」。延迟那一层,它当然有帮助,但帮助幅度远小于宣传口径;真正被改变的是你少维护一套系统、少一条同步链路、少一次「缓存与索引不一致」的排障。
这篇文章只做三件事:把 8.4 到底改了什么核清楚、把「什么情况下该塞、什么情况下是灾难」画出一条可执行的分界线、以及把我在真实项目里踩到的坑摆出来。
一、先把 8.4 到底改了什么核清楚
Redis 8.4 是 GA,不是 RC:v8.4.0,发布日期为 2025 年 11 月 18 日(官方 00-RELEASENOTES)。往前一版是 8.4-RC1(v8.3.240,2025 年 11 月 4 日),官方在 RC 的说明里明确写着「RC 是功能完整的预发布版,不适合生产使用」。所以如果你在某个公众号上看到 11 月就把 8.4-RC1 的数字当 GA 数字引用,那是不严谨的。
相对 8.2,和检索直接相关的变更只有这么几条,我按官方原文整理:
| 变更 | 官方描述里的关键限定 | 我的解读 |
|---|---|---|
FT.HYBRID |
混合检索与融合打分,支持 RRF 与 LINEAR 两种合并方式 | 关键词召回与向量召回在服务端一次完成,不用应用层自己 merge |
| 查询引擎 I/O 线程 | FT.* 命令获得吞吐提升,未给单一百分比 | 提升了并发能力,不等于单条查询变快 |
| 通用 I/O 线程 | 示例条件是「缓存场景 10% SET / 90% GET、4 核」,吞吐提升大于 30% | 这是缓存读写场景的数字,不是检索场景的数字 |
| JSON 同构数组 | 内存最多下降 91% | 只对同构数组成立,异构数组不适用 |
search-on-oom |
IGNORE / FAIL / RETURN 三值,默认 RETURN | 默认实现是「部分节点 OOM 就返回部分结果」,不报错 |
search-default-scorer |
默认打分器改为 BM25STD | 升级后相关性排序会变,线上要做 A/B |
版本状态还有一层必须说清楚:本文写作时间是 2026 年 10 月,此时 Redis 已经有 8.6 GA(2026 年 2 月 10 日)、8.8 GA(2026 年 5 月 25 日)、8.10 GA(2026 年 7 月 29 日),最新补丁是 8.10.2(2026 年 9 月 17 日)。所以「8.4 之后」不是修辞手法,是事实。8.6 把向量集的 8bit 量化与二值距离计算做了 SIMD 向量化;8.8 给 FT.HYBRID 补上了 FT.PROFILE 支持,并新增「每分片少取候选」的 KNN 参数。这几条我只核到了 release notes 的条目,没有做性能复现,标为未复现,请不要引用成基准数据。
二、演化线:从「附挂模块」到「内核能力」
要理解边界为什么消失,得把 8.0 和 8.4 连起来看。
Redis 8.0(v8.0.0,2025 年 5 月)做的是归属上的合并:RediSearch、RedisJSON、RedisTimeSeries、RedisBloom 不再是独立模块,代码并入主仓库,许可改成 RSALv2 / SSPLv1 / AGPLv3 三选一,查询引擎第一次具备水平与垂直扩展能力。注意一个容易被忽略的细节:8.0 里 Vector set 是 beta,官方就是这么标的。
8.4 做的是能力上的合并:FT.HYBRID 把「一次查询里同时做关键词召回和向量召回,再融合打分」这件事搬进了服务端。这才是边界真正模糊的那一步——在此之前,混合检索的 RRF 融合是应用层的活,你得发两次 FT.SEARCH、拿两份结果、在自己代码里按位次算分、再截断。那不是架构问题,是一段谁都不愿意维护的胶水代码。
stateDiagram-v2
[*] --> 纯缓存
纯缓存 --> 外挂模块 : 需要全文与向量检索
外挂模块 --> 内核一体 : Redis 8 合并模块
内核一体 --> 混合检索 : 8.4 提供 FT.HYBRID
混合检索 --> 检索引擎分家 : 内存成本或一致性越界
检索引擎分家 --> 纯缓存 : 检索迁出 只留缓存
这张图想让你看见的是:这条演化线不是单向的,最后一条边是我加的,也是真实会发生的——当内存成本或者一致性要求越界时,团队会把检索迁回 Elasticsearch 或者 Postgres,Redis 退回纯缓存。我在两个团队里都见过这个回退,而且回退的成本比当初「顺手加一个索引」高得多,因为那时业务已经在依赖 Redis 的相关性排序了。
三、我的判断:分界线在哪里
我的判断是:把检索放进 Redis 是否成立,只由一条不等式决定——向量与索引常驻内存的规模,必须显著小于实例内存预算。我用的阈值是 30%,超过就该重新设计。
先算清楚量级,不要凭感觉。768 维 float32 单条向量是 768 × 4 = 3072 字节,约 3KB;这还没算哈希表头、文档正文、倒排索引和 HNSW 图结构。所以:
- 10 万条文档向量 ≈ 0.3GB 裸向量,加上文档与索引开销,实际按 0.6-1GB 估
- 100 万条 ≈ 3GB 裸向量,实际按 6-10GB 估
- 1000 万条 ≈ 30GB 裸向量,实际按 60GB 以上估
最后一行就是分界线。如果你的实例是 16GB 或 32GB,1000 万条 768 维全精度向量根本放不进去,唯一的出路是量化到 8bit(把每维 4 字节压到 1 字节,size 降到四分之一)或者二值量化,代价是召回率要重新调参。这里我不太同意「先上,不行再扩」的做法:向量索引的扩容和普通缓存的扩容不是一回事,主从全量同步、RDB 加载、索引重建这几步都是内存峰值场景,线上被打到 search-on-oom 的默认 RETURN 语义,你拿到的就是部分结果而不是错误——这种「安静的错误」比超时难查得多。
所以我把结论写成两条清单。
适合塞进 Redis 的情形
- P99 要求 10ms 级别,且查询形态是「前置过滤 + top-k」,没有复杂排序
- 向量条数在百万级以内,或愿意接受 8bit 量化并重新评估召回
- embedding 模型只有 1-3 个,维度固定,不需要频繁重建索引
- 数据可以接受最终一致:索引更新滞后几百毫秒对业务无感
- 团队规模小,少一套 ES 集群带来的运维收益大于功能损失
不适合的情形
- 需要多字段相关性调权、复杂聚合、跨索引 join:这是 Elasticsearch 的地盘,不是 Redis 的地盘
- 写入强一致、要求「写完立刻能精确查到」:Redis 的索引更新和主从复制不提供这个保证
- 数据量超过内存预算且必须全量在线:量化是缓兵之计,不是解决方案
- 中文分词与词库治理需求重:查询引擎能分词,但自定义词典、同义词、停用词那一套工程化程度远不如 ES
- 需要多租户隔离、细粒度权限、审计:这些是搜索平台的能力,不是缓存的能力
四、一段能跑起来的代码,比十页 PPT 有用
1 | # 约定:$VEC 是序列化后的 768 维 float32 向量二进制,实际用客户端库或 redis-cli -x 传入 |
1 | # redis.conf 里和这条边界直接相关的四项 |
这段代码在说明什么:第一段把「文档」和「向量」放在同一个 Hash 里,这才是「缓存与检索边界消失」的物理形态——一次写入、一份内存、一个 TTL,不需要再维护一条缓存到索引的同步链路。第二段和第三段的区别是关键:* 开头的纯 KNN 是全库召回再排序,而 (@tag:{...})=>[KNN ...] 是先过滤再召回,两者的召回质量和延迟差一个量级,很多人只写了第二种却以为自己在用第一种。第四段是边界提醒:FT.AGGREGATE 能做出 GROUPBY 和 APPLY,说明它「能算」,但它的执行模型是单机内存聚合,遇到高基数分组和多重 REDUCE 就会把内存打上去,别拿它替 OLAP。
那四行配置也各有代价:io-threads 调大提升吞吐但增加上下文切换,官方给的大于 30% 是在 4 核、10% SET / 90% GET 的缓存场景测的,检索场景别直接套用;search-on-oom RETURN 是默认值,它意味着宁可给部分结果也不报错,对检索场景我倾向于改成 FAIL,让错误显式暴露;search-default-scorer BM25STD 是 8.4 改的新默认值,升级后相关性排序会漂移;lookahead 默认 16,是命令解析预取深度。
五、写路径和读路径到底长什么样
flowchart LR
subgraph WP[写路径]
A[业务写入] --> B[文档键 与 向量字段]
B --> C[索引增量更新]
C --> D[全文倒排]
C --> E[向量 HNSW 图]
end
subgraph RP[读路径]
F[查询请求] --> G[关键词召回]
F --> H[向量 KNN 召回]
G --> I[融合打分 RRF 或 LINEAR]
H --> I
I --> J[前置过滤 排序 分页]
J --> K[结果回写热点缓存]
end
D -.-> G
E -.-> H
K -.-> B
M[内存预算] -.-> D
M -.-> E
这张图想让你看见什么:写路径只有一次写内存,读路径却分成两条召回再融合,而下面那个「内存预算」节点同时约束倒排和 HNSW 两份结构——你要付的是两份索引的内存,不是一份。很多容量评估漏掉的正是这里:算向量算得很仔细,忘了倒排索引在高基数字段上的膨胀,最后 OOM 的是文本索引而不是向量。
六、Redis 8.4 / Elasticsearch / pgvector 四个维度对比
先声明:下面不是同机 benchmark,是量级判断加成本结构判断。任何让你「一个数字定生死」的对比表都不可信。
| 维度 | Redis 8.4 | Elasticsearch | pgvector |
|---|---|---|---|
| 延迟 | 亚毫秒到个位数毫秒,进程内无网络跳数 | 十毫秒级起,取决于分片与段合并状态 | 毫秒级,受 Postgres 连接池与 HNSW ef_search 影响 |
| 内存成本 | 全量常驻内存,最贵的一档 | 堆内存加堆外段缓存,磁盘为主,可接受冷数据 | 索引落盘,靠 shared_buffers 缓存,最便宜 |
| 查询能力 | 过滤加 top-k 很强,复杂聚合弱,无跨索引 join | 最强,聚合、相关性调权、分词治理齐全 | SQL 全能力加向量,复杂排序交给优化器 |
| 运维复杂度 | 最低,一套集群两种用途 | 最高,分片、映射、段合并、JVM 调优 | 最低之一,复用现有 Postgres 运维体系 |
我的理解是:这张表里真正稀缺的不是延迟,是「一致性模型」这一列没人写。Redis 给你的是最终一致加部分结果语义,ES 给你的是近实时(默认 1 秒刷新)加可调一致性,pgvector 给你的是事务级强一致。选型时先问「写入后多久必须精确可见」,这一问通常直接淘汰掉两个选项,比对比延迟有用得多。
顺带把两家的能力事实也核一下,避免用老印象选型:Elastic Stack 9.0 起,float 的 dense_vector 字段一律按 int8_hnsw 索引,bbq_disk 这类二值量化可以把大向量集的内存压下来,官方给的磁盘开销是 int8 约 25%、int4 约 12.5%、bbq 约 3.1%;pgvector 从 0.8.0(2024 年 10 月 30 日)起支持 iterative index scans,并改进了「带过滤条件时的代价估算与索引选择」——这一条恰好就是 Redis 里「前置过滤」问题的 Postgres 版答案。
七、我踩过的坑,和一处我不太同意的地方
我踩过的坑是 FT.HYBRID 的已知限制。官方在 8.4 的 release notes 里列得很直白:FT.HYBRID 的指标不出现在 FT.INFO 和 INFO 里;EXPLAINSCORE、SHARD_K_RATIO、YIELD_DISTANCE_AS、WITHCURSOR 在 FT.HYBRID 上不可用;COMBINE 之后用 FILTER 做后置过滤不可用;默认响应只给 key_id 和 score。这几条合起来意味着两件事:第一,你没法用 profile 定位一个慢的混合查询,只能靠二分法砍子句;第二,过滤必须前置到 SEARCH 和 VSIM 子句里,如果你按「先融合、再过滤」的直觉写,它会直接报不支持——而在 8.8 之前连 profile 都不给你。我第一次接这个命令时以为是语法写错,改了半天才在 release notes 的 known limitations 里找到答案。教训很朴素:新命令先读 known limitations,再读语法。
这里我不太同意「一个 Redis 顶掉 ES 加向量库」这类说法。它成立的前提是把检索需求压缩成「前置过滤加 top-k」,而这个压缩在真实业务里经常失败。反例很具体:商品搜索要按销量、好评、库存、上下架做多因子加权,还要支持类目聚合和价格区间统计,这类查询在 Redis 里要么写不出来,要么写出来是十几行 FT.AGGREGATE 的意大利面,改一次需求调一次分。更隐蔽的反例是内存——ES 允许你只把热数据放进内存、冷数据留在段文件里,Redis 不允许,你必须为全量数据付内存钱,而内存的单价是磁盘的几十倍。所以「边界消失」正确的说法是:边界从系统之间搬到了你的容量预算和一致性要求里,它没有消失,只是换了个地方收钱。
八、可以马上做的事
- 先在 release notes 里核对你要用的版本状态和 known limitations,特别是
FT.HYBRID那一串不支持项 - 用「向量条数 × 维度 × 4 字节」粗算裸向量内存,再乘 2 当作含索引的估算值,和实例内存比一比,超过 30% 就准备量化方案
- 把所有检索查询改成「前置过滤 + KNN」的写法,别用「全库 KNN 再筛」,两者召回率不是一个量级
- 生产环境把
search-on-oom从默认的 RETURN 改成 FAIL,让 OOM 显式暴露而不是返回部分结果 - 升级到 8.4 之后,因为默认打分器变成 BM25STD,要做一次线上相关性 A/B,别默认「排序没变」
- 给混合检索留一条退路:把「关键词召回」和「向量召回」的接口抽象出来,将来迁到 ES 或 pgvector 时只换实现
参考来源
- Redis Open Source 8.4 release notes(8.4 GA 与 8.4-RC1 日期、变更、known limitations):https://github.com/redis/redis/blob/8.4.0/00-RELEASENOTES
- Redis Open Source 8.0 release notes(模块合并、三许可、Vector set beta):https://github.com/redis/redis/blob/8.0.0/00-RELEASENOTES
- Redis 8.6 / 8.8 / 8.10 release notes(后续版本日期与 FT.HYBRID 增强):https://github.com/redis/redis/releases
FT.HYBRID命令参数结构(SEARCH / VSIM / COMBINE RRF 与 LINEAR):https://redis.io/docs/latest/commands/ft.hybrid/- Elasticsearch
dense_vector与量化(9.0 起 float 按 int8_hnsw 索引、bbq 磁盘开销):https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/dense-vector - pgvector 0.8.0 changelog(iterative index scans、过滤时代价估算):https://api.pgxn.org/src/vector/vector-0.8.0/CHANGELOG.md





