Redis 赢在哪三层:技术、组织、元认知

Redis 赢在三层:技术层被追平、组织层被挤压、元认知层被锁死。Caffeine 不是没机会,而是机会被结构性挤压到配角位置。

封面

我查了一下数据:掘金上 Redis 有独立标签页,内容活跃,翻页无穷;Caffeine 连独立标签页都没有,访问 juejin.cn/tag/Caffeine 直接 404。

这件事的重点不在搜索量高低。重点是开发者根本看不到 Caffeine 这个选项。

再搜一下内容分布。Redis 的搜索结果是"实战"“原理"“挑战"“最佳实践”,Caffeine 的搜索结果是"王者"“保姆级"“利器"“详解”。“王者"“保姆级"这类词指向入门科普,“实战"“原理"指向工程落地——前者在介绍自己是什么,后者在解决具体问题。教程密度差异本身就是论据:Redis 的教程多到新人会偶然撞上,Caffeine 的教程少到你不主动找就不知道它存在。

Caffeine 在 GitHub 有 17,722 stars(2026-06-28 实测,OSSInsight 数据),最新版本 3.2.4。这是个优秀 Java 库的数据。作为对比,Guava Cache 已停止维护,Caffeine 是 JVM 本地缓存的事实标准。但 stars 不等于使用广度,能成为"默认选项"的库需要 10 倍以上的生态覆盖。17k stars 的库很多,但能成为"缓存默认选项"的只有 Redis。

三个数据点(标签页 404 / 17k stars / 教程密度差异)指向同一个结构:Caffeine 不在开发者的默认视野里。

先界定清楚:这篇文章问的不是"为什么不用 Caffeine”,是"为什么 Caffeine 不是默认选项”。两者不一样。前者假设 Caffeine 应该被用,后者问的是它为什么没成为默认。你在两级缓存里用 Caffeine 做 L1(本地缓存),Redis 做 L2(分布式缓存),这不叫"用 Caffeine”,叫"用 Redis 为主、Caffeine 为辅”——Caffeine 在这个架构里是配角。

也有人会说"Redis 和 Caffeine 场景不同,不该比”。这个挡箭牌我后面会专门拆——先说结论:挡箭牌的存在本身,就是 Redis 统治力的最强证明。

我想说的是:Redis 赢在三层——技术层、组织层、元认知层。每层比上一层更难被反驳。Caffeine 的机会被这三层结构性地挤压到"配角"位置——它有机会,但机会被锁死了。

三层框架示意图——技术层/组织层/元认知层的递进结构

一、技术层:Caffeine 性能更好,但这是最不重要的结论

先把技术层面的事说清楚,因为这是最容易被拿来说事的。

Caffeine 的技术确实优秀。它用的是 W-TinyLFU 算法——通过 CountMinSketch 记录访问频率(4-bit,最大频率 15),滑动窗口实现周期性衰减(窗口切换时所有计数右移一位即除以 2,让旧频率遗忘、新频率被采纳),hill climbing 算法动态调整窗口比例。简单说就是用更少的位近似记录访问频率,既保留 LRU 对突发访问的友好,又获得 LFU 对热点数据的命中率。传统 LFU 需要为每个 key 维护独立计数器,空间开销随 key 数线性增长,W-TinyLFU 用草图结构绕开了这个问题。这是真正的算法创新。

Caffeine 的本地缓存性能也确实好,ns 级延迟,比 Redis 的 ms 级快一到两个数量级。单机读写性能上,Caffeine 完胜 Redis。

但这是最不重要的结论。

Caffeine vs Redis 技术优势对比图

为什么?三个原因。

第一,Caffeine 是 JVM 专属。它只能用在 Java、Kotlin、Scala 里。Redis 是独立服务,协议无关,任何语言都能通过 RESP 协议访问。这个差异在单语言时代不重要,在多语言微服务时代是结构性劣势。

假设一个 5 人的微服务团队:2 个 Java 服务 + Go + Python + Node.js。Caffeine 只能用在 2 个 Java 服务里,Redis 可以用在所有 5 个里。团队要统一缓存方案,只能选 Redis,Caffeine 连候选选项都进不去。

即使纯 Java 团队,Caffeine 也做不了主选项。多实例部署时 Caffeine 无法跨实例共享缓存,因为各实例缓存独立,更新时无法同步,所以一致性无解,最终还是要上 Redis。Caffeine 最多做 L1。

语言生态边界是 Caffeine 的结构性天花板。Java 开发者约占全部后端开发的 15-20%(综合 TIOBE 搜索热度和 GitHub 仓库分布的粗略估算,口径不一,仅作量级参考),这意味着即使 Caffeine 在 JVM 生态里 100% 渗透,也只能触达后端开发群体的一小部分,而 Redis 跨所有语言。这不是 Caffeine 的错,但它决定了 Caffeine 永远不可能成为"缓存默认选项”。

第二,Redis 4.0 开始也支持 LFU 淘汰策略了。用 Morris 计数器近似实现:8 bit 范围 0-255,对数增长策略,访问次数越多计数器增长越慢,默认配置下 key 在 lfu-decay-time(默认 1 分钟)内未访问则下次访问时计数器减 1(惰性衰减,非周期性批量衰减)。精度不如 Caffeine 的 W-TinyLFU,严格说两者不是同层级概念(Morris 是单 key 频率近似,CountMinSketch 是多哈希频率草图),这里比较的是"Redis 单 key 频率近似方案 vs Caffeine 全量频率草图方案"的工程取舍。Redis 配合采样淘汰(默认采样 5 个 key,淘汰频率最低的;当多个 key 频率相同时,按 LRU 策略即更久未访问的优先淘汰作为 tie-breaker)够用。

这件事直接削弱了 Caffeine 的算法优势论点。在 Redis 4.0 之前(2017 年 7 月 GA),Caffeine 的 W-TinyLFU 是真实差异化;4.0 之后,Redis 也补齐了 LFU。算法优势从"代差"变成"精度差”,Caffeine 仍然更优,但差距小到 CTO 不会因此改选型。

W-TinyLFU vs Redis Morris 算法对比

技术优势可以被追平,结构性劣势无法被突破。这是 Caffeine 宿命的本质。Caffeine 的算法优势是动态的,Redis 通过迭代补齐了 LFU;Caffeine 的结构性劣势是静态的,它永远不可能突破 JVM 边界。动态优势对静态劣势,时间站在 Redis 这边,前提是 Caffeine 的算法迭代无法突破 JVM 边界这个结构性限制。

第三,技术优势在选型决策里权重低。CTO 不会因为 Caffeine 的命中率比 Redis 高几个百分点就选 Caffeine,他会问"这几个百分点的命中率能抵消 Caffeine 的运维成本吗”。缓存命中率是技术指标,运维成本是组织指标,CTO 看的是总成本,不是单点技术指标。而且这命中率优势在实际业务里往往感知不到,瓶颈通常在 DB、在网络、在业务逻辑,不在缓存算法的命中率差异。

有人会说 Spring Boot 2.x 默认用 Caffeine。但这是"本地缓存层的默认实现",不是"缓存方案的选择"。严格说,Spring Boot 2.x 在未指定 provider 且类路径存在 Caffeine 时才默认 Caffeine;如果类路径有 Redis starter 且配置了连接,@Cacheable 默认走 Redis。Spring Boot 同时默认支持 Redis(spring-boot-starter-data-redis),开发者在 @Cacheable 上加个 Redis 配置就切过去了。框架默认不等于开发者主动选型,Spring Boot 默认 Caffeine 不等于 Caffeine 赢了,这只是框架层的便利默认,一旦需要跨实例共享,开发者会切到 Redis。Spring Boot 默认 Caffeine,是因为 Guava Cache 停止维护,Caffeine 是 JVM 本地缓存的唯一现代选择,这是"没有竞争对手的默认",不是"主动选择的默认"。

技术层 Redis 已经赢了,但这只是表层。真正让 Caffeine 出局的是下一层。

二、组织层:CTO 一拍板就是 Redis

技术层只是表层。真正让 Caffeine 出局的是组织层,非技术成因。

我模拟一个典型的 CTO 决策场景。一个 30 人的技术团队,Java 后端为主,有少量 Go 和 Python 服务。新项目要上线一个高并发读的商品详情页,QPS 预估 5k,需要缓存方案。按我参与过的几次选型会估算,这种决策通常在 10 分钟内结束,结果是 Redis。

CTO 决策场景——5 种成本权衡

老王懂 Caffeine。他知道 W-TinyLFU 算法先进,知道本地缓存 ns 级延迟。但他选 Redis 的理由全是非技术因素:

  • 运维成本:Redis 集群已有监控,Caffeine 要新建监控体系。团队已经有 Redis 的部署脚本、告警规则、值班手册,Caffeine 一切要从头来
  • 招聘成本:Redis 是招聘 JD 必备技能,新人入职不用培训;Caffeine 要花时间教,8 个开发里只有 1 个用过
  • 汇报成本:Redis 是"行业标准",选它没人质疑;选 Caffeine 要解释为什么���“为什么不用 Redis"这个问题本身就是选型摩擦
  • 风险成本:Redis 出问题有大量社区案例可查,Caffeine 出问题只能自己踩
  • 团队认知:8 个开发都熟悉 Redis 的 API 和坑,Caffeine 的最佳实践只有少数人掌握

技术优势在选型决策里权重很低。老王比较的是"选 Redis 的总成本 vs 选 Caffeine 的总成本”,而非"Redis 的技术 vs Caffeine 的技术"。技术只是总成本的一小部分。

组织层四维拆解图

这个决策逻辑不是老王个人偏好,是组织约束决定的,运维成本、招聘成本、风险成本在不同团队间高度同构。下面两组数据印证的是"招聘成本"和"团队认知"两条,不是全部五条。

招聘市场最能说明问题。Redis 是 Java 后端 JD 的默认要求,“熟练使用 Redis 是后端工程师的必备技能"这句话出现在无数招聘资讯里。随便翻 Java 后端 JD,Redis 是默认要求,Caffeine 几乎不出现,你见过哪个 JD 写"熟练使用 Caffeine”?

面试题是 JD 要求的镜像。Redis 有海量面试题集,从数据结构到持久化到分布式锁到缓存雪崩、穿透、击穿,每个点都被反复考。Caffeine 连独立的面试题集都没有,偶尔出现在"本地缓存 vs 分布式缓存"的对比题里,还是被当成另一个选项一笔带过。

企业考什么,就是企业期待你会什么。Redis 被考,说明企业默认你会用 Redis;Caffeine 不被考,说明企业根本没期待你用 Caffeine。这个信号会反向传导:开发者学 Redis 因为面试要考,不学 Caffeine 因为面试不考,进一步固化 Redis 的统治地位。

教程密度差异也是团队认知的印证(前面开场已经展示过内容分布)。Redis 的内容在解决问题,Caffeine 的内容在介绍自己。

内容深度的差异更值得玩味。Redis 有海量的事故复盘文章,缓存雪崩、穿透、击穿,每个坑都被反复讨论。Caffeine 几乎没有事故复盘内容。原因有二:一是使用规模小到事故案例积累不起来;二是 Caffeine 的故障模式与 Redis 不同,无网络、无雪崩、无穿透,主要故障是 OOM 和 GC 压力,通常归入 JVM 调优话题而非"Caffeine 事故复盘"。事故复盘多,反而是 Redis 统治地位的证明,只有大量使用才会产生大量事故。

组织层的结论是 Redis 赢,我自己踩过坑后才体会到这个结论。

我在两级缓存架构里用过 Caffeine,场景是电商订单详情页。L1 用 Caffeine,L2 用 Redis,这是社区标准方案。读路径确实快,热点 key 的 P99 从 Redis 的约 1ms(网络往返)降到 Caffeine 的约 100μs(本地访问)。

两级缓存架构示意图

但写路径的坑让我至今印象深刻。多实例部署时,L1 的一致性同步是真正的难题。三种常见方案,每种都有问题:

方案一:先更新 DB,再删 L2,再删 L1。问题:多实例部署时,实例 A 删了自己的 L1,但实例 B 的 L1 还留着旧值,B 读到脏数据直到 TTL(缓存过期时间)结束。更糟的是,如果时序反过来(先删 L1 再删 L2),实例 B 可能在 L2 删除前把旧值重新回填到 L1,删除时序本身是争议点。

方案二:Redis Pub/Sub 广播失效。实例 A 更新后广播"key X 失效",其他实例收到后删 L1。问题:Pub/Sub 不保证可靠投递,比网络抖动更常见的是订阅者断连,实例重启、滚动发布期间消息直接丢弃且无重传,L1 又脏了。

方案三:用 MQ 替代 Pub/Sub 保证可靠投递。问题:为了一个本地缓存的一致性引入 MQ,架构复杂度直线上升,而且 MQ 延迟反而把 L1 的性能优势吃掉了。

我们最后选了方案二,在 2024 年一次电商大促前的压测中出过事故。一次滚动发布导致 Pub/Sub 订阅者断连,某个实例 L1 持续返回旧值,用户看到的订单状态和实际不一致,持续到 L1 TTL(约 30 秒)过期。事后复盘,我们花了三天加补偿机制:定时任务每 10 秒对账热点 key,发现不一致主动刷新。

调完这个坑,我想通了一件事:Caffeine 在两级缓存里是配角,Redis 才是主角。L1 的存在是为了"减轻 Redis 压力";L1 的一致性问题,根源是和 Redis 的协调;所有复杂度都来自"如何在 Redis 之外再加一层"。去掉 Caffeine 系统能跑,去掉 Redis 多实例一致性直接无解,除非换 Memcached 或其他分布式缓存,但那时候你换的只是另一个"默认",不是 Caffeine。

Caffeine 的技术再好,在这个架构里也只是一个可选的优化层。这就是"配角宿命"的体感,不是 Caffeine 不好,是它的位置决定了它只能当配角。

到这里 Caffeine 在技术和组织两层都输了,但还有一层更隐蔽的锁。

三、元认知层:“场景不同"是 Redis 统治力的最强证明

技术层和组织层都能用数据和场景拆解。元认知层更隐蔽,它藏在社区讨论的默认假设里,藏在每个人说"场景不同"时的潜台词里。

“Redis 和 Caffeine 场景不同,不该比”,这是社区最常见的挡箭牌。每次有人试图比较两者,总会有人跳出来说这句话。但这个挡箭牌本身就是 Redis 统治力的最强证明。

先做一个反证。如果"场景不同"真的成立,Caffeine 应该在自己的适用场景里是默认选项。但即使在你最该用 Caffeine 的两级缓存场景里,Caffeine 也只是 L1 配角,Redis 才是 L2 主角。Caffeine 在自己最擅长的场景里都当不了默认,“场景不同"还能成立吗?

再看"场景不同"的真实含义。它说的不是"势均力敌各占一半”,而是"默认场景归 Redis,边缘场景才考虑 Caffeine”。这个"默认 vs 边缘"的划分本身就是 Redis 统治力的证据。如果 Caffeine 真的和 Redis 平起平坐,社区会说"两个都好,看团队偏好",不会发明"场景不同"这个说法来回避比较。

“场景不同"挡箭牌的自我反驳示意图

再用一个能力对比坐实。真正的"场景不同"是能力对等但定位不同,比如 Redis 和 Memcached。Memcached 是纯 KV 内存缓存,Redis 是数据结构服务,两者功能有明确分野:Memcached 做不了排行榜、HyperLogLog;在极高 QPS 的纯 KV 场景下 Memcached 多线程模型理论上有优势,但日常场景两者性能在伯仲之间。这才是真正的"场景不同”。

Redis 和 Caffeine 不是这种关系。Caffeine 在分布式能力上是 Redis 的子集(无法跨实例共享),Redis 在本地延迟上做不到 Caffeine 的水平(必经网络往返),两者不是"子集"关系,是"能力维度不重叠":一个赢在分布式,一个赢在本地。但生产缓存的刚需是分布式一致性,所以 Redis 的能力维度权重更高。

所以"场景不同"是伪命题,本质是"能力不对等下的默认选择"。当有人说"场景不同不该比"时,他其实在说:Redis 是默认选项,Caffeine 是特殊情况下的补充,你拿默认选项和特殊补充比,当然不公平。

能力维度不重叠示意图

这一层比前两层更难被反驳:技术层可以用数据拆解,组织层可以用场景还原,元认知层挑战的是社区共识,戳破它等于说"你们都在自欺欺人"。

但正因为它难被反驳,才是最深层。技术层和组织层是 Redis 统治力的成因,元认知层是 Redis 统治力的结果,社区已经把"Redis 是默认"内化为常识,用"场景不同"来维护这个常识。当共识本身成为论点的证据,说明统治力已经从"事实"变成"认知"。

认知一旦固化,改变它的成本远高于改变技术事实。Redis 的算法劣势可以被追平(事实上 Redis 4.0 已经补了 LFU),Redis 的组织优势需要 Caffeine 重建整个生态,从监控到招聘到教程到事故复盘,每一项都要从零积累。Redis 的认知优势几乎无法被打破:大家就是觉得 Redis 是默认选项,改变认知需要整个社区重新教育,这个成本没有任何一个库能承担。

这就是为什么 Caffeine 的宿命是配角。它面对的是一个三层结构:技术层被追平、组织层被挤压、元认知层被锁死。技术层可以靠迭代追平,组织层需要跨代际的长期积累,元认知层最棘手,要让整个社区承认自己一直在自欺欺人。

什么时候真的该用 Caffeine

说了这么多 Redis 赢在哪,也得诚实回答:什么时候真的该用 Caffeine?

我列一份诚实清单,不是"各有所长"的和稀泥,是明确边界。只有在满足以下条件时,Caffeine 才值得认真考虑:

  1. 单 JVM 实例部署,无跨实例一致性需求——启动加载的字典数据、单机批处理中间结果。没有一致性问题,Caffeine 的 ns 级延迟能充分发挥。Redis 的网络开销在单机场景是浪费。

  2. 热点 key 的本地预缓存(两级缓存 L1)——已有 Redis 做 L2,存在 QPS > 1k 的可识别热点 key。Caffeine 能为 Redis 减压(Redis 单实例整体 QPS 瓶颈约 10w 量级,单 key 瓶颈主要来自单线程模型下该 key 的命令排队,在 value 较大或命令复杂时更明显;Caffeine 本地缓存能扛 100k+ QPS),但必须解决 L1 一致性问题,Pub/Sub 加补偿机制,或 MQ 可靠投递。

  3. 纯 JVM 内部计算结果缓存——正则编译、反射元数据、JSON 解析结果。这些数据进程内私有,用 Redis 的网络开销(ms 级)可能比重新计算(μs 到 ms 级,取决于计算复杂度)还高,是负优化。

  4. Spring Boot 项目的本地缓存层(被动选择)——Spring Boot 2.x 默认 Caffeine,零配置开箱即用。但这是"被动接受框架默认",不是"主动选型"。一旦项目需要跨实例共享缓存,就该切到 Redis。

反过来,这些场景不该用 Caffeine:多实例需要一致性、多语言团队、需要持久化、需要跨服务共享、团队不熟悉 JVM 调优。

如果你的团队是单 JVM 且纯读场景为主,Caffeine 值得认真考虑。其他场景,Redis 是更安全的选择。

Caffeine 使用边界清单

Caffeine 的技术越好,它的优势场景在生产缓存里占比越低,因为生产缓存的瓶颈在分布式一致性,不在本地命中率。技术优势改变不了结构性位置,这是 Caffeine 的宿命。

原文发布于 止语Lab


关于止语Lab

一个工程师的深度技术笔记。

不写入门教程,不追热点。只写那些真正折腾过、想通了的东西。

了解更多 →