Alibaba 开源框架,基于 Spring 和 Redis 的分布式缓存框架
缓存管理:JetCache 提供了 CacheBuilder 类来创建缓存,以及 Cache 对象来操作缓存,例如 get、put、remove 等。在调用 Cache 对象的 put 方法时,可以使用注解 @Cache 来设置缓存时间和名称等配置。
注解支持:JetCache 提供了多种注解来实现缓存操作,例如 @Cached,@CacheUpdate, @CacheInvalidate 等,通过使用注解的方式,可以更加方便地进行缓存操作,例如缓存预热、删除、更新等。
<dependency>
<groupId>com.alicp.jetcachegroupId>
<artifactId>jetcache-annoartifactId>
<version>2.7.3version>
dependency>
<dependency>
<groupId>com.alicp.jetcachegroupId>
<artifactId>jetcache-coreartifactId>
<version>2.7.3version>
dependency>
import com.alicp.jetcache.anno.CacheConsts;
import com.alicp.jetcache.anno.SerialPolicy;
import com.alicp.jetcache.anno.config.EnableMethodCache;
import com.alicp.jetcache.anno.support.GlobalCacheConfig;
import com.alicp.jetcache.anno.support.JetCacheBaseBeans;
import com.alicp.jetcache.embedded.CaffeineCacheBuilder;
import com.alicp.jetcache.support.DecoderMap;
import com.alicp.jetcache.support.Fastjson2KeyConvertor;
import com.alicp.jetcache.support.Fastjson2ValueDecoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import java.util.HashMap;
import java.util.Map;
@Configuration
// 要扫描的类的基本路径 即支持的路径
@EnableMethodCache(basePackages = {"com.xxx.xxx.xxx.xx"})
@Import(JetCacheBaseBeans.class)
public class MyJetCacheConfig {
@Bean
public GlobalCacheConfig config() {
DecoderMap.defaultInstance().initDefaultDecoder();
DecoderMap.defaultInstance().register(SerialPolicy.IDENTITY_NUMBER_FASTJSON2, Fastjson2ValueDecoder.INSTANCE);
Map localBuilders = new HashMap();
CaffeineCacheBuilder localBuilder =
CaffeineCacheBuilder.createCaffeineCacheBuilder().keyConvertor(Fastjson2KeyConvertor.INSTANCE)
.limit(100);
// 设置默认缓存时间 单位毫秒
localBuilder.setExpireAfterWriteInMillis(60 * 60 * 1000);
localBuilders.put(CacheConsts.DEFAULT_AREA, localBuilder);
Map remoteBuilders = new HashMap();
GlobalCacheConfig globalCacheConfig = new GlobalCacheConfig();
globalCacheConfig.setLocalCacheBuilders(localBuilders);
globalCacheConfig.setRemoteCacheBuilders(remoteBuilders);
globalCacheConfig.setStatIntervalMinutes(15);
globalCacheConfig.setPenetrationProtect(true);
return globalCacheConfig;
}
}
@Service
public class UserServiceImpl implements IUserService {
@Cache(name = "自定义的当前缓存名", key = "#userId", expire = 300, cacheType = CacheType.LOCAL)
@Override
public User getUserById(Long userId) {
// 具体内部自己的业务实现
.......
}
@CacheUpdate(name = "自定义的当前缓存名2", key = "#user.id") // user.id 会自动获取当前方法入参的对象的id 属性 作为缓存的key 类似于Map
@Override
public void updateUser(User user) {
// 具体内部自己的业务实现
......
}
}
@Cache 属性说明:
属性 | 说明 |
---|---|
area | 如果在配置中配置了多个缓存area,在这里指定使用哪个area |
name | 指定缓存的唯一名称,不是必须的,如果没有指定,会使用类名+方法名。name会被用于远程缓存的key前缀。另外在统计中,一个简短有意义的名字会提高可读性。 |
key | 使用 spring EL 表达式 指定key,如果没有指定会根据所有参数自动生成。 |
expire | 超时时间。如果注解上没有定义,会使用全局配置,如果此时全局配置也没有定义,则为无穷大 |
timeUnit | 指定expire的单位,默认为 TimeUnit.SECONDS 秒 |
cacheType | CacheType.REMOTE 缓存的类型,包括CacheType.REMOTE、CacheType.LOCAL、CacheType.BOTH。如果定义为BOTH,会使用LOCAL和REMOTE组合成两级缓存 |
localLimit | 如果cacheType为LOCAL或BOTH,这个参数指定本地缓存的最大元素数量,以控制内存占用。如果注解上没有定义,会使用全局配置,如果此时全局配置也没有定义,则为100,参数 localLimit 表示本地缓存的最大条目限制。当使用 JetCache 的本地缓存功能时,localLimit 参数可以控制本地缓存中最多缓存的条目数量,如果超过了这个数量,将会按照 LRU(Least Recently Used)算法删除最近最少使用的缓存条目,以保持缓存的大小在限制范围内。localLimit 默认值为 100条,可以通过设置该值来优化缓存性能和内存使用。备注:当type为LOCAL时,配置localLimit,当key值超出限制条件,会删除最少使用的条目,重新请求缓存过的,会走到db再缓存一次。当type为BOTH时,虽然配置了localLimit 当key值超出限制条件,本地会删除使用最少得条目,但是远程还有缓存,查询缓存时是优先查询本地,没有再去远程,都没有再走db,将查询结果进行一次缓存。如果配置BOTH时,可以配置该项减少本地内存使用,但是不影响缓存整体使用因为有远程兜底。 |
localExpire | 仅当cacheType为BOTH时适用,为内存中的Cache指定一个不一样的超时时间,通常应该小于expire |
serialPolicy | 指定远程缓存的序列化方式。可选值为SerialPolicy.JAVA和SerialPolicy.KRYO。如果注解上没有定义,会使用全局配置,如果此时全局配置也没有定义,则为SerialPolicy.JAVA |
keyConvertor | 指定KEY的转换方式,用于将复杂的KEY类型转换为缓存实现可以接受的类型,当前支持KeyConvertor.FASTJSON和KeyConvertor.NONE。NONE表示不转换,FASTJSON可以将复杂对象KEY转换成String。如果注解上没有定义,会使用全局配置。 |
enabled | 默认true 是否激活缓存。例如某个dao方法上加缓存注解,由于某些调用场景下不能有缓存,所以可以设置enabled为false,正常调用不会使用缓存,在需要的地方可使用CacheContext.enableCache在回调中激活缓存,缓存激活的标记在ThreadLocal上,该标记被设置后,所有enable=false的缓存都被激活 |
cacheNullValue | 默认 false 当方法返回值为null的时候是否要缓存 |
condition | 使用SpEL指定条件(spring EL 表达式),如果表达式返回true的时候才去缓存中查询 |
postCondition | 使用SpEL指定条件(spring EL 表达式),如果表达式返回true的时候才更新缓存,该评估在方法执行后进行,因此可以访问到 #result |
@CacheRefresh 属性说明:
属性 | 说明 |
---|---|
refresh | 刷新间隔 |
timeUnit | 默认 TimeUnit.SECONDS 秒 时间单位 |
stopRefreshAfterLastAccess | 指定该key多长时间没有访问就停止刷新,如果不指定会一直刷新 |
refreshLockTimeout | 默认 60秒 类型为BOTH/REMOTE的缓存刷新时,同时只会有一台服务器在刷新,这台服务器会在远程缓存放置一个分布式锁,此配置指定该锁的超时时间 |
@CacheInvalidate 属性说明:
属性 | 说明 |
---|---|
area | 如果在配置中配置了多个缓存area,在这里指定使用哪个area,指向对应的@Cached定义。 |
name | 指定缓存的唯一名称,指向对应的@Cached定义。 |
key | 使用SpEL指定key |
condition | 使用SpEL指定条件,如果表达式返回true才执行删除,可访问方法结果#result |
@CacheUpdate 属性说明:
属性 | 说明 |
---|---|
area | 如果在配置中配置了多个缓存area,在这里指定使用哪个area,指向对应的@Cached定义。 |
name | 指定缓存的唯一名称,指向对应的@Cached定义。 |
key | 使用SpEL指定key |
value | 使用SpEL指定value |
condition | 使用SpEL指定条件,如果表达式返回true才执行删除,可访问方法结果#result |
@CachePenetrationProtect 注解:
当缓存访问未命中的情况下对并发进行的加载行为进行保护。
当前版本实现的是单JVM内的保护,即同一个JVM中同一个key只有一个线程去加载,其它线程等待结果。
对于以上未定义默认值的参数,如果没有指定,将使用yml中指定的全局配置
依赖
后缀为 redis 即支持redis 远程缓存
<dependency>
<groupId>com.alicp.jetcachegroupId>
<artifactId>jetcache-starter-redisartifactId>
<version>3.0.1version>
dependency>
yml 配置文件
jetcache:
# 统计间隔,默认0:表示不统计
statIntervalMinutes: 1
# areaName是否作为缓存key前缀,默认True
areaInCacheName: false
local:
default:
# 已支持可选:linkedhashmap、caffeine
type: linkedhashmap
# key转换器的全局配置,当前只有:fastjson, @see com.alicp.jetcache.support.FastjsonKeyConvertor
keyConvertor: fastjson
# 每个缓存实例的最大元素的全局配置,仅local类型的缓存需要指定
limit: 100
# jetcache2.2以上,以毫秒为单位,指定多长时间没有访问,就让缓存失效,当前只有本地缓存支持。0表示不使用这个功能
expireAfterAccessInMillis: 60000
remote:
default:
# 已支持可选:redis、tair
type: redis.lettuce
# 连接格式@see:https://github.com/lettuce-io/lettuce-core/wiki/Redis-URI-and-connection-details
uri: redis://localhost:6379/1?timeout=5s
keyConvertor: fastjson
# 序列化器的全局配置。仅remote类型的缓存需要指定,可选java和kryo
valueEncoder: java
valueDecoder: java
# 以毫秒为单位指定超时时间的全局配置
expireAfterWriteInMillis: 5000
全局开关运行类
@SpringBootApplication
@EnableMethodCache(basePackages = "com.xxx.xxxx.xxxx")
@EnableCreateCacheAnnotation
public class MySpringBootApp {
public static void main(String[] args) {
SpringApplication.run(MySpringBootApp.class);
}
}
本地缓存
LinkedHashMapCache是JetCache中实现的一个最简单的Cache,使用LinkedHashMap做LRU方式淘汰。
Cache<String, Xxxx> cache = LinkedHashMapCacheBuilder.createLinkedHashMapCacheBuilder()
.limit(100)
.expireAfterWrite(200, TimeUnit.SECONDS)
.buildCache();
内部为key 和 value 的返回值
本地缓存-caffeine
caffeine cache 是guava cache的后续作品
Cache<String, Xxxx> cache = CaffeineCacheBuilder.createCaffeineCacheBuilder()
.limit(100)
.expireAfterWrite(200, TimeUnit.SECONDS)
.buildCache();
内部为key 和 value 的返回值
统计信息
当yml中的 jetcache.statIntervalMinutes 大于0时,通过 @CreateCache 和 @Cached 配置出来的 Cache 自带监控。JetCache会按指定的时间定期通过logger输出统计信息。
开启配置
@Bean
public Consumer<StatInfo> statCallback() {
// ... 或实现自己的Consumer
return new StatInfoLogger(false);
}