多级缓存核心是请求优先命中caffeine本地缓存(纳秒级),未命中再查redis(毫秒级),最后查数据库,并按序回填;更新时采用cache aside模式删除缓存而非更新,辅以消息广播或ttl兜底保障一致性。

在 Spring Boot 中配置多级缓存(Caffeine + Redis),核心是让高频请求优先命中本地内存,大幅减少网络调用,从而把系统吞吐量从“Redis 级”拉升到“本地级”。这不是简单堆砌两个缓存组件,而是要有明确的层级分工、统一的访问路径和可控的一致性策略。
选型与依赖:Caffeine 做 L1,Redis 做 L2
本地缓存必须轻量、低延迟、高命中率;分布式缓存必须可共享、易管理、支持淘汰。Spring 生态中已形成事实标准:
- Caffeine:Spring 5+ 官方推荐替代 Guava 的本地缓存,基于 W-TinyLFU 算法,读写性能比 Guava 高 4 倍以上,支持最大容量、过期时间、引用类型等精细控制
- Redis:用
spring-boot-starter-data-redis(非 reactive 版即可满足大多数场景),配合StringRedisTemplate或泛型RedisTemplate操作
引入依赖示例:
<dependency><groupid>com.github.ben-manes.caffeine</groupid><artifactid>caffeine</artifactid></dependency><dependency><groupid>org.springframework.boot</groupid><artifactid>spring-boot-starter-data-redis</artifactid></dependency>
分层访问逻辑:按顺序穿透,命中即止
所有读请求必须走同一入口,不能有的走 @Cacheable,有的手动查 Redis,否则缓存策略会失控。推荐封装成统一 Service 方法:
- 先查 Caffeine 缓存(
cache.getIfPresent(key)),命中直接返回,耗时纳秒级 - 未命中则查 Redis(如
redisTemplate.opsForValue().get(key)),命中后立即写入 Caffeine 并返回 - Redis 也未命中,查数据库,成功后先写 Redis(设合理 TTL),再写 Caffeine(TTL 可略短于 Redis,比如 1/3~1/2)
注意:Caffeine 不建议设永不过期,应配合主动刷新或较短 TTL(如 10 分钟),避免脏数据长期滞留。
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
更新一致性:用 Cache Aside + 失效通知,不更新缓存
写操作不更新两级缓存,而是删除 Redis 缓存,并触发本地缓存失效——这是避免并发不一致最稳妥的方式:
- 更新数据库成功后,调用
redisTemplate.delete("key") - 通过消息队列(如 RocketMQ)、Redis Pub/Sub 或 Spring Event,广播“缓存失效事件”,各节点收到后调用
caffeineCache.invalidate(key) - 不推荐“先删缓存再更新 DB”或“先更新 DB 再更新缓存”,高并发下极易出现中间态不一致
若无消息中间件,可接受短暂不一致,采用“超时自动失效”策略:Redis TTL 设为 30 分钟,Caffeine TTL 设为 5 分钟,靠时间兜底。
监控与调优:看命中率,不只看速度
多级缓存是否生效,不能只测接口响应时间,关键看各级命中率:
- Caffeine 提供
cache.stats(),暴露 hitCount、missCount、evictionCount,可暴露为 Actuator 指标 - Redis 用
INFO stats查keyspace_hits/misses,或用redis-cli --stat实时观察 - 如果 Caffeine 命中率低于 70%,说明热点不集中或缓存容量太小;如果 Redis 命中率低于 50%,可能需检查 Key 设计或预热机制
调优方向很明确:增大 Caffeine maximumSize(如 10000)、调整 expireAfterWrite 和 expireAfterAccess 组合、为不同业务域设置独立缓存实例。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










