JAVA项目中使用Caffeine和Redis实现二级(多级)缓存
JAVA项目中使用Caffeine和Redis实现二级(多级)缓存
1. 什么是多级缓存?适合什么样的业务场景?
1.1 什么是多级缓存?
多级缓存指在系统中同时使用不同层级、不同类型的缓存,一般分为:
| 层级 | 名称 | 位置 | 特点 |
|---|---|---|---|
| 一级缓存(L1) | 本地缓存,如 Caffeine | 应用 JVM 内存中 | 极快(纳秒级)、无网络开销、容量有限、无法跨实例共享 |
| 二级缓存(L2) | 分布式缓存,如 Redis | 独立缓存服务器 | 稳定共享、容量大、需要网络通信、延迟高于本地缓存 |
多级缓存 = L1(极快) + L2(共享)优势互补
- 一级缓存(本地缓存):直接与应用程序关联,适合频繁访问的数据。
- 二级缓存(远程缓存):作为一级缓存的补充,存储相对较不常访问的数据。
1.2 使用二级缓存(Caffeine + Redis)的优势
用最小成本获得最高性能,并保证缓存的数据一致性和高可用性。
1 | |
A. 性能优势 —— 延迟更低,吞吐量更高
- L1 本地缓存(Caffeine)—— 纳秒级读取
- L2 分布式缓存(Redis)—— 毫秒级共享访问
- 当 L1 未命中,L2 仍能快速响应
- 缓解数据库压力
多级缓存 = 用 L1 提高速度,用 L2 兜底和共享
B. 稳定性优势 —— 降低 Redis 压力、防雪崩
- 防止 Redis 被热点击穿
- 大量访问直接在 L1 缓存中完成,不打 Redis
- Redis 故障时系统仍可降级运行
- Redis 挂掉后:L1 缓存仍然有效, 系统不会立即雪崩式崩溃
C. 兼具高性能与一致性
- L1 缓存解决速度瓶颈
- L2 缓存提供跨节点一致数据
1.3 什么业务场景适合Caffeine?
适合的业务场景:
- Caffeine 适合需要快速访问、短期存储的数据场景,如频繁查询的热点数据、计算结果缓存等,尤其是在高并发环境下表现优异。
不适合的业务场景
- Caffeine不适合实时性要求高或数据变更频繁的场景
- Caffeine也不适合需要强一致性保证的数据存储,因为它主要关注性能和命中率,而不是数据的一致性。
2. JAVA项目中如何实现 Caffeine + Redis 的二级缓存体系
2.0 前提
- 你的项目已经形成了初步的微服务架构
2.1 总体结构和查询流程
利用 Caffeine 构建本地高速缓存作为 L1,Redis 构建分布式缓存作为 L2,并通过自定义注解 + AOP + 自动装配,实现了高性能、低延迟、可控的一致性缓存架构,各微服务只需引入 aimin-cache 模块即可无侵入式使用二级缓存。
aimin-cache模块
查询流程
- 先查本地 Caffeine
- 本地没有 → 查询 Redis
- Redis 没有 → 查询数据库
- 设置 Redis + Caffeine 双缓存
- 更新数据时同步清除两级缓存
写数据流程
- update DB → 删除 Redis → 删除 Caffeine
优先删除Redis?
- 避免 Redis 仍保留旧数据
- 先清除redis中缓存数据,然后清除caffeine中的缓存,避免短时间内如果先清除caffeine缓存后其他请求会再从redis里加载到caffeine中
1 | |
2.2 引入依赖
在aimin-cache模块的pom.xml文件中引入以下依赖:
| 依赖 | 作用 |
|---|---|
spring-boot-starter-cache |
启用 Spring Cache 框架(Cacheable/CacheEvict) |
spring-boot-starter-aop |
启用 AOP(用于你项目的自定义缓存注解切面) |
caffeine |
L1 本地高速缓存 |
aimin-redis |
Redis 客户端封装,用于 L2 缓存 |
hutool-json、hutool-crypto |
处理缓存值 JSON 序列化、加解密 |
mybatis-plus |
用于 BaseCacheService 需要调用数据库时使用 |
1 | |
2.3 对缓存的一些配置 cache.yml
- 总体结构配置
- 一级缓存(Caffeine)配置
- 二级缓存(Redis)配置
- l2cache(Caffeine 二级本地缓存,用于 Redis 前置)配置
1 | |
2.4 aimin-cache 整体模块
- 有两套二级缓存体系
- 一个“轻量级简单版”和一个“企业级正式版”
| 分支 | 包路径 | 用处 |
|---|---|---|
| simple 版 | com.oimc.aimin.cache.simple.* |
通过注解 @L2Cache + AOP 实现二级缓存(简单且易用) |
| formal 版 | com.oimc.aimin.cache.formal.* |
完整企业级二级缓存体系(CacheManager + Caffeine + Redis + 消息同步) |
2.4.1 simple 版(注解式)二级缓存 — 适合业务层快速使用
simple 版由以下核心类组成:
- L2Cache 注解(定义缓存规则)
- L2CacheAspect AOP 切面(实现二级缓存逻辑)
- SimpleCacheProperties(配置 Caffeine)
- L2CacheConfig(创建 Caffeine + 配置)
- ElParser(解析 SpEL,生成缓存 key)
这套是 “AOP 自动织入 + Caffeine + RedisTemplate” 形式。
2.4.2 formal版二级缓存 — Spring Cache + CacheManager + 消息同步
包括:
- AiminCacheAutoConfiguration自动配置类(装配整个缓存体系)
- AiminCacheManager(创建缓存实例)
- AiminCache(整合 Caffeine + Redis 的实际缓存实现)
- L2RedisCache(Redis 操作封装)
- CacheMessageListener(Redis pub/sub 清除本地缓存)
- BaseCacheService(业务使用封装)
2.5 详细分析aimin-cache-simple包中的各个类
2.5.1 @L2Cache 注解(定义二级缓存行为)
提供:
- cacheName:缓存名称
- key:支持 SpEL 的动态 key
- type:CacheType(QUERY/PUT/DELETE 等)
特点:
- 查询顺序:Caffeine → Redis → DB
- 更新顺序:DB → Redis → Caffeine
1 | |
2.5.2 L2CacheAspect — 缓存 AOP 实现(核心逻辑)
这是 AOP + 注解方式的二级缓存
- (1) 拦截带 @L2Cache 的方法
1 | |
- (2) 解析 key(SpEL)
1 | |
- (3) QUERY 类型:两级缓存查询顺序
1 | |
- (4) PUT 类型:写入两级缓存
1 | |
- (5) DELETE 类型:删除两级缓存
1 | |
2.5.3 config
CacheType: 缓存操作类型枚举:定义 @L2Cache 的工作模式SimpleCacheProperties—— simple 体系下的 Caffeine 配置L2CacheConfig—— 创建 simple 版二级缓存所需的 Caffeine 实例
1 | |
- CacheType 决定缓存操作行为
- SimpleCacheProperties 读取并处理配置文件参数
- L2CacheConfig 根据这些参数创建 Caffeine 缓存实例,供 AOP 切面(L2CacheAspect)使用。
一、CacheType(缓存操作类型枚举)—— 定义 @L2Cache 的工作模式
这个枚举表示「调用 @L2Cache 注解时,缓存要怎么工作」。
它是 缓存使用策略的枚举类型,对应 AOP 切面 L2CacheAspect 的不同执行分支。
① FULL —— 完整查询模式(默认)
1 | |
查询顺序:
Caffeine(L1)→ Redis(L2)→ 方法本体(DB)→ 更新缓存
这是最典型的二级缓存逻辑,适合查询方法:
1 | |
特点:
- 会先查缓存,不命中才查数据库。
- 查到的数据会写入两级缓存。
② PUT —— 强制更新缓存模式
1 | |
特点:
- 不查缓存,直接执行方法体(通常是 DB 查询/更新)。
- 把新的数据写入 L1 + L2 缓存。
用途:
当业务要确保缓存最新时:
1 | |
③ DELETE —— 删除缓存模式
1 | |
用途:
- 用于删除某个缓存键
- 或清空整个缓存(根据 key & cacheName)
例子:
1 | |
二、SimpleCacheProperties —— simple 体系下的 Caffeine 配置
这个类是 读取配置文件(cache.yml → l2cache.*)的属性载体(ConfigurationProperties)。
对应你 yml 里这段:
1 | |
它的功能是:
把 yml 中 Caffeine 缓存的配置读取出来,并转换为 Java 能使用的参数。
三、L2CacheConfig —— 创建 simple 版二级缓存所需的 Caffeine 实例
这个类是 simple 模式的核心配置类:
根据 SimpleCacheProperties 创建一个 Caffeine 缓存 Bean(一级缓存 L1)。
同时:
- 标记 @EnableCaching → 启用 Spring Cache
- 让 AOP + 缓存注解可以工作
核心方法:创建 Caffeine Cache Bean
1 | |
作用:
- 创建一个 全局唯一 的 Caffeine 本地缓存实例
- 作为 simple 模式的一级缓存
- 被 L2CacheAspect 注入,用于缓存查询/写入/删除
2.5.4 ElParser
ElParser 用于解析 @L2Cache 注解中的 SpEL(Spring Expression Language)表达式,从方法参数生成最终的缓存 Key。
它让你可以写:
1 | |
而程序能自动得到真实缓存 key:
1 | |
2.6 详细分析aimin-cache-formal包中的各个类
- AiminCacheAutoConfiguration自动配置类(装配整个缓存体系)
- AiminCacheManager(创建缓存实例)
- AiminCache(整合 Caffeine + Redis 的实际缓存实现)
- L2RedisCache(Redis 操作封装)
- CacheMessageListener(Redis pub/sub 清除本地缓存)
- BaseCacheService(业务使用封装)
2.6.1 AiminCacheAutoConfiguration — 自动装配入口
只要你的微服务依赖 aimin-cache,Spring Boot 会自动启动二级缓存体系
- (1) 创建 Redis 二级缓存工具类 L2RedisCache
1 | |
- (2) 创建 AiminCacheManager(整个缓存体系的中心)
1 | |
- (3) 创建 Redis 监听器,用于多节点同步缓存
1 | |
2.6.2 AiminCacheManager — 负责创建每个缓存
getCache(name):创建/获取缓存实例
1 | |
它实际返回的 Cache 是:
- Caffeine 作为 L1
- Redis 作为 L2
- 包装成 AiminCache
AiminCacheManager 内部不仅管理缓存实例,还负责:
- dynamic = true 时允许动态创建 cacheName
- 使用自定义 Caffeine 配置
详见 caffeineCache() 方法
2.6.3 AiminCache — 真正的二级缓存实现(核心中的核心)
它继承 Spring 的 AbstractValueAdaptingCache
成员组成
| 成员 | 作用 | 示例代码 |
|---|---|---|
| L1:Caffeine | 本地高速缓存 | private Cache<Object,Object> l1CaffeineCache |
| L2:Redis | 分布式缓存 | private L2RedisCache l2RedisCache |
| 配置 | 控制缓存策略 | AiminCacheConfig caffeine/redis/composite |
| 加锁机制 | 解决缓存击穿 | ReentrantLock[] lockArray |
⭐ lookup() 方法:二级缓存查询核心
1 | |
二级缓存读取顺序:
Caffeine → Redis → DB,然后回填 Caffeine
⭐ put() 方法:写入顺序
- 写入 Redis(以 ms 为单位)
- 写入 Caffeine
- 发布同步消息(用于集群同步)
⭐ clearLocal():用于集群同步
2.6.4 L2RedisCache — Redis 缓存层封装
支持:
- set(key, value, timeout)
- get(key)
- hashAdd
- deleteKeys
RedisTemplate 由自动配置注入。
2.6.5 CacheMessageListener — 集群缓存同步
Redis 发布/订阅 pub/sub
收到消息 → 清除本地节点的 L1 Caffeine 缓存:
让多个服务节点保持一致。
1 | |
2.6.6 BaseCacheService — 给业务层使用的统一封装
业务层真正使用的入口:
1 | |
负责:
- 自动生成 Key(使用 MD5) → keyGen()
- 自动获取缓存(cache.get)
- 不命中 → 走数据库 → 写入缓存
2.7 跨微服务使用:其他微服务如何使用二级缓存?
2.7.1 微服务只需引入aimin-cache模块,即可自动开启二级缓存
aimin-admin的启动类添加注解
@SpringBootApplication@EnableCaching
1 | |
@SpringBootApplication注解会自动导入AiminCacheAutoConfiguration
- 自动加载配置
cache.yml - 自动注册
CacheManager - 自动注册切面
L2CacheAspect - 自动开启缓存
2.7.2 业务调用方式(两种)
simple版:直接使用自定义注解
1 | |
formal版:BaseCacheService
1 | |
然后直接使用:
1 | |