应采用caffeine+redis两级缓存架构:caffeine负责纳秒级本地热点数据快筛,redis承担跨节点共享与穿透防护,通过合理过期策略、空值缓存、布隆过滤器及“先删后写”等机制保障一致性与高可用。

直接用本地 Caffeine 挡住大部分读请求,再用 Redis 承接跨节点共享和兜底查询,数据库自然就轻松了。关键不是堆层数,而是让每层干好自己的事、失效可控、出问题能快速降级。
本地缓存(Caffeine)做第一道快筛
Caffeine 运行在 JVM 内存里,读取延迟在纳秒级,没有网络开销,适合拦截高频、低变更的热点数据,比如用户基本信息、配置项、字典码、权限白名单等。
- 设置合理容量和过期策略,例如
.maximumSize(10000).expireAfterWrite(10, TimeUnit.MINUTES),避免内存膨胀或数据长期 stale - 不存大对象(如整张订单列表),可只缓存 ID 列表,查时再按需加载
- 开启统计功能:
.recordStats(),后续接入 Micrometer 上报命中率、加载耗时、淘汰数等指标 - Spring Boot 2.4+ 默认支持 Caffeine,配合
@Cacheable使用时,需自定义CacheManager并启用weakKeys防止内存泄漏
Redis 作为共享层和穿透防护中枢
本地缓存解决不了集群内一致性问题,Redis 就是第二道防线,统一出口,同时承担缓存穿透、击穿、雪崩的防御职责。
- Key 命名带业务前缀与版本号,例如
user:v2:10086,方便灰度切换和批量清理 - 值建议用 JSON 字符串或序列化 byte[],避免反序列化兼容风险;高频小字段可用 Redis Hash 结构节省空间
- TTL 必须设,且加入随机偏移,例如基础 10 分钟 ± 60 秒,防大量 Key 同时过期引发雪崩
- 空值缓存(null + 短 TTL)配合布隆过滤器,拦截非法 ID 请求,大幅降低无效 DB 查询
读写流程要清晰,避免脏数据堆积
读操作走“Caffeine → Redis → DB”三级穿透;写操作必须保证顺序和可控性,不能靠监听 Redis 事件来清本地缓存——网络延迟和消息丢失会让它不可靠。
- 读流程:先查 Caffeine,命中则返回;未命中查 Redis;Redis 未命中再查 DB,并把结果同步回填 Redis 和 Caffeine
- 写流程推荐“先删后写”:删除 Caffeine 中对应 key → 删除 Redis 中对应 key → 写 DB → (异步)回填 Redis(防止 DB 写成功但缓存写失败)
- 本地缓存失效用服务内广播(Spring ApplicationEvent)或轻量消息(如 Redis Stream)通知其他节点,而不是监听 Redis 的 keyevent
- 对一致性要求极高的场景(如资金类操作),跳过 Caffeine,直读 Redis + DB,用分布式锁或 CAS 保障更新安全
监控和降级能力决定系统韧性
没监控的缓存就是定时炸弹。缓存是否健康,得靠数据说话;系统是否稳,要看能不能随时切流、熔断、降级。
- Caffeine 统计指标通过
MeterRegistry接入 Prometheus/Grafana,重点关注 hitRate、evictionCount、loadExceptionRate - Redis 层监控命令耗时、连接池使用率、超时率、慢日志,Jedis/Lettuce 均支持开箱 metrics
- 配置运行时开关(如 Nacos/Apollo 动态属性),支持一键关闭本地缓存、切换为只读 Redis、甚至全量走 DB(熔断)
- 缓存层异常时自动降级,例如 Caffeine 加载失败直接跳过,Redis 不可用则退化为 DB 直查,避免雪崩传导
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











