【接口缓存】Alibaba - JetCache
😄 生命不息,写作不止
🔥 继续踏上学习之路,学之分享笔记
👊 总有一天我也能像各位大佬一样
🏆 一个有梦有戏的人 @怒放吧德德
🌝分享学习心得,欢迎指正,大家一起学习成长!
来记录一下我近期所学的jetcache缓存的使用,希望各为读者能理解,如有错误请指正!
简介
jetcache是Alibaba开源的缓存访问工具框架,比起spring cache来说是更加强大。jetcache是基于java的缓存系统封装,提供统一的API和注解来简化缓存的使用。可以通过注解创建缓存实例,也可以直接在接口、方法上直接设置。 JetCache提供了比SpringCache更加强大的注解,可以原生的支持TTL、两级缓存、分布式自动刷新,还提供了Cache接口用于手工缓存操作。 当前有四个实现,RedisCache、TairCache(此部分未在github开源)、CaffeineCache(in memory)和一个简易的LinkedHashMapCache(in memory),要添加新的实现也是非常简单的。
全部特性:
通过统一的API访问Cache系统
通过注解实现声明式的方法缓存,支持TTL和两级缓存
通过注解创建并配置
Cache实例
针对所有Cache实例和方法缓存的自动统计
Key的生成策略和Value的序列化策略是可以配置的
分布式缓存自动刷新,分布式锁 (2.2+)
异步Cache API (2.2+,使用Redis的lettuce客户端时)
Spring Boot支持
官方文档:
https://github.com/alibaba/jetcache/blob/master/docs/CN/GettingStarted.md
实例
本次测试使用springboot2.x,redis作为远程缓存
导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alicp.jetcache/jetcache-starter-redis -->
<dependency>
<groupId>com.alicp.jetcache</groupId>
<artifactId>jetcache-starter-redis</artifactId>
<version>2.6.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.51</version>
</dependency>
配置文件yml
jetcache:
statIntervalMinutes: 15 # 统计间隔,默认0:表示不统计
areaInCacheName: false # areaName是否作为缓存key前缀,默认True
local:
default: # 默认default,可以配置更多的area
type: linkedhashmap # 已支持可选:linkedhashmap、caffeine
keyConvertor: fastjson # key转换器
remote:
default:
type: redis
keyConvertor: fastjson
valueEncoder: java # 序列化器,只有remote需要
valueDecoder: java # 序列化器,只有remote需要
poolConfig:
minIdle: 5
maxIdle: 20
maxTotal: 50
host: 127.0.0.1
port: 6379
配置介绍:
属性 | 默认值 | 说明 |
---|---|---|
jetcache.statIntervalMinutes | 0 | 统计间隔,0表示不统计 |
jetcache.areaInCacheName | true(2.6-) false(2.7+) | jetcache-anno把cacheName作为远程缓存key前缀,2.4.3以前的版本总是把areaName加在cacheName中,因此areaName也出现在key前缀中。2.4.4以后可以配置,为了保持远程key兼容默认值为true,但是新项目的话false更合理些,2.7默认值已改为false。 |
jetcache.hiddenPackages | 无 | @Cached和@CreateCache自动生成name的时候,为了不让name太长,hiddenPackages指定的包名前缀被截掉 |
jetcache.[local/remote].${area}.type | 无 | 缓存类型。tair、redis为当前支持的远程缓存;linkedhashmap、caffeine为当前支持的本地缓存类型 |
jetcache.[local/remote].${area}.keyConvertor | 无 | key转换器的全局配置,当前只有一个已经实现的keyConvertor:fastjson。仅当使用@CreateCache且缓存类型为LOCAL时可以定为none,此时通过equals方法来识别key。方法缓存必须指定keyConvertor |
jetcache.[local/remote].${area}.valueEncoder | java | 序列化器的全局配置。仅remote类型的缓存需要指定,可选java和kryo |
jetcache.[local/remote].${area}.valueDecoder | java | 序列化器的全局配置。仅remote类型的缓存需要指定,可选java和kryo |
jetcache.[local/remote].${area}.limit | 100 | 每个缓存实例的最大元素的全局配置,仅local类型的缓存需要指定。注意是每个缓存实例的限制,而不是全部,比如这里指定100,然后用@CreateCache创建了两个缓存实例(并且注解上没有设置localLimit属性),那么每个缓存实例的限制都是100 |
jetcache.[local/remote].${area}.expireAfterWriteInMillis | 无穷大 | 以毫秒为单位指定超时时间的全局配置(以前为defaultExpireInMillis) |
jetcache.remote.${area}.broadcastChannel | 无 | jetcahe2.7的两级缓存支持更新以后失效其他JVM中的local cache,但多个服务共用redis同一个channel可能会造成广播风暴,需要在这里指定channel,你可以决定多个不同的服务是否共用同一个channel。如果没有指定则不开启。 |
jetcache.local.${area}.expireAfterAccessInMillis | 0 | 需要jetcache2.2以上,以毫秒为单位,指定多长时间没有访问,就让缓存失效,当前只有本地缓存支持。0表示不使用这个功能。 |
通过 @CreateCache 注解创建 Cache 实例
通过@CreateCache注解创建一个缓存实例,默认超时时间是100秒, 配置cacheType等参数
缓存类型有CacheType.REMOTE,CacheType.LOCAL,CacheType.BOTH(两级缓存)
@CreateCache(expire = 100, cacheType = CacheType.REMOTE)
private Cache<Long, User> testCache;
属性值
testCache是本类全局可用,如果是需要整个项目全局可用,可以通过@Component用bean的方式将实例推送给spring管理。
使用起来也很方便,通过使用该实例的api即可。比如以下代码,通过put将值存入缓存,由于是采用REMOTE的方式,会将数据存储到redis中。
testCache.put(123L, testService.getUserById(1L));
获取数据
User s = testCache.get(123L);
通过注解实现方法缓存
详细看官方介绍:https://github.com/alibaba/jetcache/blob/master/docs/CN/MethodCache.md
官方介绍的例子这里就不粘贴了,@JetCache,@CacheUpdate,@CacheInvalidate
可以写在接口上
/**
* @Author: lyd
* @Description:
* @Date: 2022-08-24
*/
public interface TestService {
@Cached(name="userCache.", key="#userId", expire = 100, cacheType = CacheType.REMOTE, keyConvertor = KeyConvertor.FASTJSON, serialPolicy = SerialPolicy.JAVA)
@CacheRefresh(refresh = 1800, stopRefreshAfterLastAccess = 3600, timeUnit = TimeUnit.SECONDS)
@CachePenetrationProtect
User getUserById(long userId);
}
或者可以是直接在方法上
/**
* @Author: lyd
* @Description:
* @Date: 2022-08-24
*/
@Service
public class TestServiceImpl implements TestService {
@Cached(name="userCache.", key="#userId", expire = 100, cacheType = CacheType.REMOTE, keyConvertor = KeyConvertor.FASTJSON, serialPolicy = SerialPolicy.JAVA)
@CacheRefresh(refresh = 1800, stopRefreshAfterLastAccess = 3600, timeUnit = TimeUnit.SECONDS)
@CachePenetrationProtect
@Override
public User getUserById(long userId) {
// 模拟数据库查询数据
User u = new User();
u.setId(userId);
u.setName("爱国德德");
u.setAge(18);
return u;
}
}
使用的时候直接调用该接口,第一调用会进入方法体,然后将返回的数据保存到缓存中,下次访问接口的时候,如果缓存还没过期就会直接获取数据,不必再去数据库查询数据。
还有一些更加高级的api以及相关信息可以去官网查看阅读。
参考阅读
简书 https://www.jianshu.com/p/41b2d92b40e7
👍创作不易,如有错误请指正,感谢观看!记得一键三连哦!👍