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

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

01 引言

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

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

我们一起来了解一下吧!

02 JetCache简介

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

当前有 RedisCache、TairCache(未开源)、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.8和Spring 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表示同时使用本地缓存和远程缓存,这里可以指定任意一个缓存使用。
  • 属性中name和key的拼接组成Redis中的key
  • key使用的是EL表达式,通过#取属性的值
  • @CacheRefresh的refresh指每隔多长时间刷新一次缓存

缓存更新效果

再次请求缓存已经更新

@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 Boot、Jedis、JetCache版本兼容问题

05 小结

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

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

相关推荐
ym hyd 1113 小时前
试题库管理系统源码 Java+SpringBoot+Vue3 前后分离
java·vue.js·spring boot·毕设
AC赳赳老秦4 小时前
采集行为合规自检:OpenClaw 自动校验 robots 协议与采集频率,规避违规采集风险
java·开发语言·c++·python·php·deepseek·openclaw
钱栈up4 小时前
mvn compile 卡死在 javac 阶段:一次类型不匹配的排查与修复
java·开发语言
怕浪猫5 小时前
Prompt Engineering 面试怎么考?这 5 个范式你必须会
面试·程序员·github
吠品5 小时前
CSS图片模糊过渡:一个transition加filter就够
java·数据库·notepad++
步行cgn6 小时前
Spring 全注解开发详解
java·后端·spring
长河6 小时前
Java的GC(垃圾回收)中,标记无用对象的核心方法是可达性分析算法
java·jvm·算法
code2cat7 小时前
Java进阶篇之LongAdder:把统计更新分散,再读取总和
java·并发编程·原子类·longadder
凯哥Java7 小时前
写代码怎么避免逻辑漏洞?
java·开发语言·人工智能·自动化
Ivanqhz7 小时前
正余弦位置编码(Sinusoidal Positional Encoding)
java·linux·数据库