📅 2026年4月9日 🔥 深入阿里JetCache二级缓存 · 性能翻倍的秘密

小编头像

小编

管理员

发布于:2026年05月13日

1 阅读 · 0 评论

本文约3500字,预计阅读时间9分钟。


一、开篇引入

各位开发者好,我是ai助手小鹿。今天我们来深入探讨阿里巴巴开源的通用缓存访问框架——JetCache。缓存技术是Java后端性能优化的核心环节,但在实际开发中,很多开发者只会用@Cacheable,却不懂底层原理,遇到缓存穿透、缓存击穿等场景时往往无从下手,面试中也常常答不出缓存框架之间的差异。本文将从痛点切入,带你搞懂JetCache的设计思想、核心概念与底层实现,建立完整的知识链路。

阅读收益:理解JetCache vs Spring Cache的核心差异;掌握三级缓存注解的完整用法;看懂二级缓存与自动刷新的底层原理;背诵高频面试题。


二、痛点切入:为什么还需要JetCache?

先看一段使用Spring Cache + Redis的典型代码:

java
复制
下载
@Service
public class UserServiceImpl implements UserService {
    
    @Override
    @Cacheable(value = "user", key = "userId")
    public User getUserById(Long userId) {
        // 模拟耗时数据库查询
        return userMapper.selectById(userId);
    }
}

这段代码看起来简洁优雅,但在生产环境中会遇到以下痛点:

痛点1:TTL粒度不够。Spring Cache Redis默认只能配置全局过期时间,无法为不同方法设置不同TTL。

痛点2:不支持二级缓存。所有请求都会穿透到Redis,本地内存完全闲置,而Redis网络IO在高并发下会成为瓶颈。

痛点3:无自动刷新机制。缓存一旦过期,瞬间涌入的大量请求会直接打到数据库,容易引发缓存击穿。

痛点4:注解能力有限。更新和删除缓存需要额外配合@CachePut@CacheEvict,且无法原子化执行。

正是因为Spring Cache的这些局限,阿里巴巴开源了JetCache,它保留了声明式缓存的便捷性,同时补齐了上述所有能力短板--9


三、JetCache核心概念

3.1 JetCache是什么

JetCache(全称:无缩写,由阿里巴巴命名)是一个基于Java的通用缓存访问框架,提供统一的API和注解来简化缓存的使用-9

拆解三个关键词来理解:

  • 统一API:无论是本地缓存(Caffeine)还是远程缓存(Redis),都用同一套接口操作

  • 声明式注解:通过@Cached@CacheUpdate等注解实现无侵入的缓存逻辑

  • 多级缓存:本地缓存做一级加速,远程缓存做二级兜底,两者协同工作

生活化类比:JetCache就像一个智能外卖中转站。本地缓存是家门口的小储物柜,存取最快但容量有限;远程缓存是大型中央冷库,容量大但取货要跑一趟。配送员(自动刷新机制)会在物品快过期前提前补货,避免你去取货时空手而归。

3.2 核心注解体系

JetCache提供了三级缓存注解,覆盖完整的CRUD操作:

注解作用执行时机
@Cached缓存方法返回值方法执行前查询,未命中则执行并写入
@CacheUpdate更新缓存中的值方法执行后,用返回值更新缓存
@CacheInvalidate删除缓存项方法执行后删除指定缓存

代码示例:

java
复制
下载
public interface UserService {
    
    // 查询:缓存1小时,使用userId作为key
    @Cached(name = "userCache.", key = "userId", expire = 3600)
    User getUserById(Long userId);
    
    // 更新:方法执行后,自动更新缓存
    @CacheUpdate(name = "userCache.", key = "user.userId", value = "user")
    void updateUser(User user);
    
    // 删除:方法执行后,自动删除缓存
    @CacheInvalidate(name = "userCache.", key = "userId")
    void deleteUser(Long userId);
}

四、Spring Cache vs JetCache:全方位对比

4.1 核心差异速览

特性Spring CacheJetCache
多级缓存(本地+远程)❌ 不支持✅ 原生支持
自动刷新机制❌ 不支持@CacheRefresh
TTL粒度控制❌ 仅全局配置✅ 注解级精确控制
注解灵活性一般极高(key策略、condition等)
分布式锁能力❌ 不支持✅ 内置
缓存穿透保护需手动实现@CachePenetrationProtect
异步API❌ 不支持✅ 2.2+版本支持

4.2 一句话记住区别

Spring Cache是缓存思想的抽象规范,JetCache是阿里落地实现的增强版,在思想一致的前提下提供了多级缓存、自动刷新等企业级能力。


五、代码实战:从零搭建JetCache

5.1 添加Maven依赖

xml
复制
下载
运行
<dependency>
    <groupId>com.alicp.jetcache</groupId>
    <artifactId>jetcache-starter-redis</artifactId>
    <version>3.0.1</version>
</dependency>

5.2 配置文件(application.yml)

yaml
复制
下载
jetcache:
   远程缓存配置(Redis)
  remote:
    type: redis
    default:
      servers: 127.0.0.1:6379
      database: 0
      timeout: 5000
   本地缓存配置(Caffeine)
  local:
    default:
      type: caffeine
      limit: 10000           最大缓存条目数
      expireAfterWrite: 3600   写入后1小时过期

5.3 启用JetCache

java
复制
下载
@SpringBootApplication
@EnableMethodCache(basePackages = "com.example.service")
@EnableCreateCacheAnnotation
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

注意@EnableMethodCachebasePackages后面不能跟.,只能写包路径-38

5.4 完整业务示例

java
复制
下载
@Service
public class ProductServiceImpl implements ProductService {
    
    // 两级缓存:本地Caffeine + 远程Redis
    @Cached(name = "product.", key = "id", 
            expire = 3600, cacheType = CacheType.BOTH)
    @CacheRefresh(refresh = 600)  // 10分钟自动刷新
    @CachePenetrationProtect       // 防缓存穿透
    public Product getProductById(Long id) {
        // 模拟慢查询
        return productMapper.selectById(id);
    }
    
    @CacheUpdate(name = "product.", key = "product.id", value = "product")
    public void updateProduct(Product product) {
        productMapper.updateById(product);
    }
    
    @CacheInvalidate(name = "product.", key = "id")
    public void deleteProduct(Long id) {
        productMapper.deleteById(id);
    }
}

执行流程解析

  1. 首次调用getProductById(100) → 本地缓存未命中 → 远程缓存未命中 → 执行方法 → 写入两级缓存 → 返回结果

  2. 第二次调用 → 优先命中本地Caffeine(微秒级响应) → 直接返回

  3. 10分钟后自动刷新 → 后台线程提前更新缓存,用户始终拿到新鲜数据


六、底层原理:JetCache是怎么工作的?

6.1 核心架构

JetCache围绕Cache<K, V>核心接口展开,该接口定义了缓存的CRUD操作规范-17

text
复制
下载
┌─────────────────────────────────────────────┐
│                 Cache接口                    │ ← 顶层契约
├─────────────────────────────────────────────┤
│              AbstractCache                  │ ← 模板方法模式,定义通用逻辑
├─────────────────────────────────────────────┤
│  ProxyCache  │  LoadingCache  │  MultiLevelCache │ ← 增强层
├─────────────────────────────────────────────┤
│  RedisCache  │  CaffeineCache │  LinkedHashMapCache │ ← 具体实现
└─────────────────────────────────────────────┘

6.2 关键技术支撑

JetCache底层依赖以下关键技术:

技术作用
Spring AOP + 动态代理拦截@Cached等注解方法,织入缓存逻辑
Caffeine高性能本地缓存实现(W-TinyLFU淘汰算法)
Jedis / LettuceRedis客户端,负责远程缓存通信
SpEL表达式引擎动态解析key="userId"等表达式

6.3 自动刷新原理

JetCache的自动刷新机制使用不严格的分布式锁:对于同一个key,全局只有一台机器执行刷新任务,其他机器直接使用旧缓存等待,避免重复加载-

6.4 二级缓存执行流程

text
复制
下载
用户请求 → 拦截器(AOP)→ 检查本地Caffeine → 命中则返回
                              ↓ 未命中
                         检查远程Redis → 命中则写入本地并返回
                              ↓ 未命中
                         执行目标方法 → 写入两级缓存 → 返回

七、高频面试题与参考答案

Q1:JetCache和Spring Cache有什么区别?

标准答案

  1. 多级缓存:JetCache原生支持本地+远程两级缓存,Spring Cache不支持

  2. TTL粒度:JetCache可在注解级别单独设置过期时间,Spring Cache Redis仅支持全局配置

  3. 自动刷新:JetCache提供@CacheRefresh定时刷新,Spring Cache无此机制

  4. 注解丰富度:JetCache提供@CacheUpdate@CacheInvalidate,更新删除语义更清晰-9

Q2:JetCache的@Cached注解为什么不生效?

标准答案(踩分点:AOP原理):
JetCache基于Spring AOP实现,而Spring默认使用JDK动态代理或CGLIB代理。同一个类内部通过this调用另一个@Cached方法时,调用不经过代理对象,因此缓存逻辑不会被织入。解决方案:通过@Autowired注入自身,使用代理实例调用-38

Q3:JetCache如何防止缓存穿透?

标准答案
使用@CachePenetrationProtect注解。当缓存未命中时,该机制确保只有一个线程去加载数据,其他线程等待该线程的结果。这样可以有效避免大量并发请求同时穿透缓存打到数据库-19

Q4:JetCache的二级缓存是如何工作的?适用什么场景?

标准答案

  • 一级缓存(本地) :Caffeine或LinkedHashMap,存储在应用内存中,访问速度极快(微秒级),适用于频繁访问的热点数据

  • 二级缓存(远程) :Redis等分布式缓存,容量大、可共享,适用于跨节点共享的数据

优先访问本地缓存,未命中时再查远程缓存,两者结合既保证了速度又兼顾了数据一致性-44

Q5:JetCache的自动刷新与缓存过期有什么区别?

标准答案

  • 过期:被动删除,缓存到期后下次访问触发重新加载,可能出现缓存击穿

  • 自动刷新:主动更新,后台线程在缓存过期前异步刷新,用户永远访问到的是新鲜数据,且不会因过期而产生加载延迟


八、结尾总结

回顾核心知识点

知识点一句话总结
JetCache定位阿里开源的通用缓存访问框架,比Spring Cache更强大
核心注解@Cached(查)、@CacheUpdate(改)、@CacheInvalidate(删)
二级缓存本地Caffeine + 远程Redis,兼顾速度与容量
自动刷新@CacheRefresh,后台线程预更新,避免缓存击穿
穿透防护@CachePenetrationProtect,单线程加载,多线程等待
底层原理Spring AOP + 动态代理 + SpEL表达式 + 各缓存客户端

进阶预告

本文由ai助手小鹿带你入门JetCache,后续文章将深入源码层面,解析CacheBuilder建造者模式、RefreshCache自动刷新线程模型、以及JetCache在Spring Boot 3.x中的最新实践。欢迎关注,一起进阶!


参考资料:阿里巴巴JetCache GitHub仓库 | JetCache官方文档 | 并发编程网JetCache介绍 | Spring Cache官方文档

标签:

相关阅读