关于Jetcache的使用
😄生命不息,写作不止
🔥 继续踏上学习之路,学之分享笔记
👊 总有一天我也能像各位大佬一样
🌝分享学习心得,欢迎指正,大家一起学习成长!
JetCache是由阿里巴巴开源的通用缓存访问框架,是个非常好用的一个开发工具。
基本使用
本文简单介绍jetcache的使用,通过引入坐标,再到简单重要的注解的使用。
引入依赖
xml
<dependency>
<groupId>com.alicp.jetcache</groupId>
<artifactId>jetcache-starter-redis</artifactId>
<version>2.7.3</version>
</dependency>
使用的2.7+的版本,需要额外添加该依赖
xml
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.3.1</version>
</dependency>
激活注解
需要在启动器类上加上两个注解,EnableMethodCache,EnableCreateCacheAnnotation这两个注解分别激活Cached和CreateCache注解。
java
@EnableMethodCache(basePackages = "org.nl")
@EnableCreateCacheAnnotation
配置
在application.yml中配置
yaml
jetcache:
statIntervalMinutes: 15
areaInCacheName: false
local:
default:
type: linkedhashmap
keyConvertor: fastjson
remote:
default:
type: redis
keyConvertor: fastjson2
broadcastChannel: projectA
valueEncoder: java
valueDecoder: java
poolConfig:
minIdle: 5 # 连接池中的最小空闲连接数
maxIdle: 20 # 连接池中的最大空闲连接数
maxTotal: 50 # 连接池中的最大连接数
host: 127.0.0.1
port: 6379
jetcache.statIntervalMinutes:这个属性指定了Jetcache统计信息的刷新间隔,单位为分钟。Jetcache会定期收集并更新缓存的统计信息,以便监视缓存的性能和使用情况。 jetcache.areaInCacheName:这个属性用于确定是否将缓存区域(cache area)的名称包括在缓存名称中。 jetcache.local/remote:配置本地缓存,即在应用程序内存中的缓存。或者(配置远程缓存,通常是分布式缓存,如Redis。) jetcache.local/remote.default.type:本地/远程缓存的类型。这里指定为 linkedhashmap,表示使用LinkedHashMap作为本地缓存的实现。 jetcache.local/remote.default.keyConvertor:用于将本地/远程的缓存键序列化和反序列化的键转换器。这里使用了fastjson,表示使用Fastjson库进行键的转换。 jetcache.remote.default.broadcastChannel:如果您的应用程序需要缓存广播功能,可以指定广播通道的名称。 jetcache.remote.default.valueEncoder:用于将缓存值序列化的值编码器。这里使用了java,表示使用Java序列化来编码缓存值。 jetcache.remote.default.valueDecoder:用于将缓存值反序列化的值解码器。 jetcache.remote.default.poolConfig:配置redis连接池参数
常用方法
@Cached注解
- name:通过name来指定缓存的唯一名称,不是必须的,如果没有指定,会使用类名+方法名。name会被用于远程缓存的key前缀。可以自己定义,就只是个前缀。
- key:使用SpEL指定key,如果没有指定会根据所有参数自动生成。会与name进行拼接,可以使用形参的内容来。
- expire:过期时间
以下以项目中的系统参数来做demo
首先,不设置key,这样会默认将参数的数据作为key,会极大的不友好。
java
@Cached(name = "paramData.", expire = 3600, cacheType = CacheType.REMOTE)
Page<Param> queryPage(Map whereJson, PageQuery page);
因为参数是使用了Map来的,会导致redis的key很杂,后续没办法对其进行更新。
接下来设置一下key值,这里是可以使用SpEL表达式,可以直接输入数字,输入字符串需要加上''
。否则会报错,如果使用字符串而没有加上''
就会被默认是使用参数字段。
java
@Cached(name = "paramData.", key = "open", expire = 3600, cacheType = CacheType.REMOTE)
Page<Param> queryPage(Map whereJson, PageQuery page);
以上是没有''
来区分字符串,代码中就会出现SpelEvaluationException
错误
加上''
java
@Cached(name = "paramData.", key = "'open'", expire = 3600, cacheType = CacheType.REMOTE)
Page<Param> queryPage(Map whereJson, PageQuery page);
也可以是使用参数,需要注意的是,修改的时候需要去触发修改或者失效。
@CacheUpdate @CacheInvalidate
java
@Cached(name = "paramDataCode.", key = "#code", expire = 3600, cacheType = CacheType.REMOTE)
Param findByCode(String code);
加上之后可以在redis中查看,key值就比较清晰易懂。
也可以使字符串+参数的拼接
java
@Cached(name = "paramData.", key = "'open' + #page.size + #page.page", expire = 3600, cacheType = CacheType.REMOTE)
IPage<Param> queryPage(Map whereJson, PageQuery page);
那么,如果只是这样创建的话,当数据更新之后,只要没达到过期时间,数据也还是会是旧数据。
jetcache提供了更新的注解,当每次调用了更新方法,就会让对应的缓存数据失效。
java
@CacheInvalidate(name = "paramData.", key = "'open'")
void update(Param param);
:::info 使用@CacheUpdate和@CacheInvalidate的时候,相关的缓存操作可能会失败(比如网络IO错误),所以指定缓存的超时时间是非常重要的。 :::
@CacheUpdate注解
更新数据注解,当运行该注解下的方法,就会更新所对应的值,如果没有更新,只能等待自动过期。常用参数有:name, key, value,name和key是拼接起来对应在redis的key,value是对应的值,也是需要替换的值。
如以下官方文档
java
public interface UserService {
@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);
}
当userCache-1的值改动了,就会将新的数据覆盖。
如以下例子,通过code获取参数表中的数据,并缓存起来。
java
@Cached(name = "paramDataCode.", key = "#code", expire = 3600, cacheType = CacheType.REMOTE)
Param findByCode(String code);
当对其进行更新数据时候,需要把这个缓存中的数据也更新。
java
@CacheInvalidate(name = "paramData.", key = "'open'")
@CacheUpdate(name = "paramDataCode.", key = "#param.code", value = "#param")
void update(Param param);
@CacheInvalidate注解
@CacheInvalidate是用来使缓存失效的注解,通过name,key来确定失效的缓存。
*分页查询不适合用缓存
java
@Cached(name = "paramData.", key = "'open'", expire = 3600, cacheType = CacheType.REMOTE)
Page<Param> queryPage(Map whereJson, PageQuery page);
@CacheInvalidate(name = "paramData.", key = "'open'")
void create(Param param);
@CacheRefresh注解
用于配置缓存刷新策略。它可以标注在方法上,表示当缓存失效时,将会触发指定的方法来重新加载缓存数据。
java
@CacheRefresh(name = "myCache", timeUnit = TimeUnit.MINUTES, refresh = 10)
public void refreshCache(String key);
name = "myCache" 指定了要刷新的缓存名称。 timeUnit = TimeUnit.MINUTES 指定了时间单位为分钟。 refresh = 10 指定了刷新的时间间隔为10分钟。
:::info *注:
方法的返回类型必须是 void。
方法的参数可以是缓存键或与缓存键相关的信息,用于定位需要刷新的缓存项。
方法的参数列表必须与缓存方法(被 @Cached 注解的方法)的参数列表相匹配。 :::
@CachePenetrationProtect注解
用于防止缓存击穿,通过在多个并发请求中只有一个请求去加载数据,其他请求等待加载完成后直接从缓存获取。
java
@CachePenetrationProtect
@Cached(name = "paramData.", key = "'open' + #page.size + #page.page", expire = 3600, cacheType = CacheType.REMOTE)
@CacheRefresh(refresh = 3, stopRefreshAfterLastAccess = 60*60, refreshLockTimeout = 0)
IPage<Param> queryPage(Map whereJson, PageQuery page);
CacheManager
使用CacheManager可以创建Cache实例,area和name相同的情况下,它和Cached注解使用同一个Cache实例。
注意:在jetcache 2.7 版本CreateCache注解已经废弃,请改用CacheManager.getOrCreateCache(QuickConfig)
使用demo
java
@Autowired
private CacheManager cacheManager;
private Cache<String, Param> userCache;
@PostConstruct
public void init() {
QuickConfig qc = QuickConfig.newBuilder("userCache")
.expire(Duration.ofSeconds(100))
.cacheType(CacheType.REMOTE) // two level cache
.syncLocal(true) // invalidate local cache in all jvm process after update
.build();
userCache = cacheManager.getOrCreateCache(qc);
}
// 方法内使用
userCache.put("name", param); // 写缓存
System.out.println(userCache.get("name")); // 读缓存
CreateCache注解
可以直接创建缓存实例
java
@CreateCache(expire = 100)
private Cache<Long, UserDO> userCache;
对应属性表
总结
本篇记录了笔者在开发中会使用到的注解/方法,对于其字段含义也做了一定的备注。