缓存性能王者,阿里巴巴二级缓存JetCache框架

关注我的公众号:【编程朝花夕拾】,可获取首发内容。

01 引言

上一节介绍了本地缓存相关的使用以及坑点,本地缓存的使用往往带有局限性,用的更多的依然还是类似Redis这样的分布式缓存。

阿里巴巴出品的JetCache正是整合了本地缓存和分布式缓存,由框架自动管理本地缓存和远程缓存。提供了注解驱动的声明是缓存,同时也提供缓存的管理器CacheManage,可以随时手工接管缓存的使用。

我们一起来了解一下吧!

02 JetCache简介

JetCache 是一个 Java 缓存抽象框架,为不同缓存解决方案提供统一使用方式,其注解功能比 Spring Cache 更强大。它支持原生 TTL、两级缓存、分布式环境下自动刷新,还能通过代码操作缓存实例。

当前有 RedisCacheTairCache(未开源)、CaffeineCache LinkedHashMapCache 四种实现。其具备多种特性,如通过统一缓存 API 操作缓存、支持带 TTL 和两级缓存的注解式方法缓存、可创建及配置缓存实例、自动收集缓存访问统计信息、自定义键生成和值序列化策略、支持多种缓存键和值转换器、分布式缓存自动刷新和分布式锁、异步访问、更新后使本地缓存失效以及 Spring Boot支持等。

环境要求:

  • JDK1.8
  • Spring Framework4.0.8+ (optional, with annotation support),jetcache 2.7 need 5.2.4+
  • Spring Boot 1.1.9+ (optional), jetcache 2.7 need 2.2.5+

Github地址:github.com/alibaba/jet...

03 使用案例

3.1 Maven

案例基于Spring Boot 2.6.13

xml 复制代码
<dependency>
    <groupId>com.alicp.jetcache</groupId>
    <artifactId>jetcache-starter-redis</artifactId>
    <version>2.7.8</version>
</dependency>

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>4.4.3</version>
</dependency>

jetcache-starter-redis默认使用的是Jedis客户端。因为jetcache-starter-redis 2.7.8Spring Boot 2.6.13有冲突,需要引入Jedis 4.x版本。

否则就是出现部分类找不到的现象:

3.2 配置文件

properties 复制代码
jetcache.statIntervalMinutes=15
jetcache.areaInCacheName=false
#还可以选caffeine
jetcache.local.default.type=linkedhashmap   
#还可以选fastjson/fastjson2
jetcache.local.default.keyConvertor=jackson  
jetcache.local.default.limit=100

jetcache.remote.default.type=redis
#还可以选fastjson/fastjson2
jetcache.remote.default.keyConvertor=jackson  
#还可以选kryo/kryo5
jetcache.remote.default.valueEncoder=java 
#还可以选kryo/kryo5
jetcache.remote.default.valueDecoder=java     
jetcache.remote.default.poolConfig.minIdle=5
jetcache.remote.default.poolConfig.maxIdle=20
jetcache.remote.default.poolConfig.maxTotal=50
# 集群配置
jetcache.remote.default.cluster[0]=127.0.0.1:7000
jetcache.remote.default.cluster[1]=127.0.0.1:7001
jetcache.remote.default.cluster[2]=127.0.0.1:7002

JetCache的配置并没有提示,所以配置的时候要注意,防止配错。

详细的配置说明:github.com/alibaba/jet...

启动类的注解

@EnableMethodCache(basePackages = "xx.xx.xx")

3.3 注解使用案例

注解可以加在接口上,也可以加在类上。案例以在类上使用为例。

常用注解:

  • @Cached
  • @CacheUpdate
  • @CacheInvalidate
  • @CacheRefresh

@Cached@CacheRefresh

java 复制代码
/**
 * @Description: 新增/刷新缓存
 *
 * @Author: ws
 * @Date: 2025/7/22 13:45
 **/
@Cached(expire = 3600, cacheType = CacheType.BOTH, name = "cache_key_", key = "#userId")
@CacheRefresh(refresh = 10)
@RequestMapping("test01")
public String test01(String userId) {
    System.out.println(LocalDateTime.now().format(FORMAT) + " userId=" + userId);
    return "test01" + Instant.now().toEpochMilli();
}

代码注意事项:

  • CacheType.BOTH表示同时使用本地缓存和远程缓存,这里可以指定任意一个缓存使用。
  • 属性中namekey的拼接组成Redis中的key
  • key使用的是EL表达式,通过#取属性的值
  • @CacheRefreshrefresh指每隔多长时间刷新一次缓存

缓存更新效果

再次请求缓存已经更新

@CacheUpdate

java 复制代码
/**
 * @Description: 更新缓存
 *
 * @Author: ws
 * @Date: 2025/7/22 13:45
 **/
@CacheUpdate(name = "cache_key_", key = "#userId", value = "#val")
@RequestMapping("test03")
public String test03(String userId, String val) {
    return "缓存更新成功!";
}

这里要说明的更新的value的值也是通过EL表达式从参数中获取的,无法指定方法中的数据作为缓存的结果

@CacheInvalidate

java 复制代码
/**
 * @Description: 更新缓存
 *
 * @Author: ws
 * @Date: 2025/7/22 13:45
 **/
@CacheInvalidate(name = "cache_key_", key = "#userId")
@RequestMapping("test04")
public String test04(String userId) {
    return "缓存失效!";
}

这里值得注意的是,这里的缓存失效,会将远程的缓存失效以及本机的缓存失效,其他节点的本地缓存并不能同步失效。

3.4 手动API接管

java 复制代码
@Autowired
CacheManager cacheManager;

@RequestMapping("test02")
public String test02(String userId) {
    Cache<String, String> cacheKey = cacheManager.getCache("cache_key_");
    if (cacheKey == null) {
        return  "cache_key_ 不存在";
    }
    if (cacheKey instanceof MultiLevelCache cache) {
        Cache[] caches = cache.caches();
        Arrays.stream(caches).forEach(item -> {
            if (item instanceof LinkedHashMapCache) {
                System.out.println("LinkedHashMapCache:" + item.get(userId));
            }else if (item instanceof RedisCache) {
                System.out.println("RedisCache:" + item.get(userId));
            }
        });
    }
    return cacheKey.get(userId);
}

效果

3.5 命中率统计

JetCache自带了统计功能,每隔一段时间就会输出统计数据。通过jetcache.statIntervalMinutes配置控制

04 关键注意事项

因为结合本地缓存和远程缓存,那么框架就存在这两者的优势和劣势。使用的时候也需要注意:

  • 缓存防止大Key的出现
  • 本地缓存需要增加容量限制
  • 结合TTL和主动失效
  • 多节点本地缓存不同步的问题
  • 使用时Spring BootJedisJetCache版本兼容问题

05 小结

通过合理利用JetCache的同步机制和缓存策略,可显著提升系统性能并保障数据一致性。建议结合具体业务场景进行参数调优,并持续监控缓存健康度。

使用任何一个框架,我们也要考虑可能带来的问题。线下发现不了,线上就会教会我们了。

相关推荐
Dcs10 分钟前
Spring Framework 6.2 正式发布:开发者最值得关注的更新全览!
java
别来无恙14911 分钟前
Spring Boot自动装配原理深度解析:从核心注解到实现机制
java·spring boot·后端
亲爱的非洲野猪12 分钟前
Spring Cloud Gateway 电商系统实战指南:架构设计与深度优化
java·spring cloud·gateway
[听得时光枕水眠]13 分钟前
Gateway
java·开发语言·gateway
m0_4811473327 分钟前
枚举类高级用法
java·开发语言·windows
开往198232 分钟前
@DateTimeFormat、@JsonFormat、@JSONField区别及用法
java·前端·时间·datetime
愿你天黑有灯下雨有伞1 小时前
Spring Boot+Redis Zset:三步构建高可靠延迟队列系统
spring boot·redis·后端
慕y2741 小时前
Java学习第六十三部分——K8s
java·开发语言·学习
bobz9651 小时前
交换机上的DMZ的优先级比ACL的限制的优先级更高么
后端
你我约定有三2 小时前
RabbitMQ--批量处理
java·windows·后端·rabbitmq