【接口缓存】Alibaba – JetCache

【接口缓存】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;

属性值

【接口缓存】Alibaba - JetCache
testCache是本类全局可用,如果是需要整个项目全局可用,可以通过@Component用bean的方式将实例推送给spring管理。
使用起来也很方便,通过使用该实例的api即可。比如以下代码,通过put将值存入缓存,由于是采用REMOTE的方式,会将数据存储到redis中。

testCache.put(123L, testService.getUserById(1L));

【接口缓存】Alibaba - JetCache
获取数据

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

?创作不易,如有错误请指正,感谢观看!记得一键三连哦!?