二级缓存JetCache

来!咱们聊聊如何把缓存玩出一种境界! https://www.csrbobo.com/4b4634eb423d4450a4720546193ff9d0/4b4634eb423d4450a4720546193ff9d0.html

JetCache code  https://github.com/alibaba/jetcache

JetCache wiki  https://github.com/alibaba/jetcache/wiki/Home_CN

1 简介

 JetCache是一个基于java的缓存系统封装,提供统一个API和注解来简化缓存的使用。JetCache提供了比SpringCache更加强大的注解,可以原生的支持TTL、两级缓存、分布式自动刷新,还提供了Cache接口用于手工缓存操作。

当前有四个实现,RedisCache、TairCache(https://github.com/alibaba/tair)、CaffeineCahe(in memory)和 LinkedHashMapCache(in memory),要添加新的实现也是非常简单的。

全部特性:

  • 通过统一的API访问Cache系统
  • 通过注解实现声明式的方法缓存,支持TTL和两级缓存
  • 通过注解创建并配置cache实例
  • 针对所有Cache实例和方法缓存的自动统计
  • Key的生成策咯和Value的序列化策咯是可以配置的
  • 分布式自动刷新,分布式锁
  • 异步Cache API(使用redis的lettuce客户端时)
  • Spring Boot支持

2 springBoot使用方式

2.1 引入依赖

<dependency>
    <groupId>com.alicp.jetcache</groupId>
    <artifactId>jetcache-starter-redis</artifactId>
    <version>${jetcache.latest.version}</version>
</dependency>

2.2 Application加上注解

@SpringBootApplication
@EnableMethodCache(basePackages = "com.company.mypackage")
@EnableCreateCacheAnnotation
public class MySpringBootApp {
    public static void main(String[] args) {
        SpringApplication.run(MySpringBootApp.class);
    }
}

2.3 配置文件

jetcache:
  statIntervalMinutes: 5
  areaInCacheName: false
  local:
    default:
      type: caffeine
      keyConvertor: fastjson
      limit: 2000
  remote:
    default:
      type: redis
      keyConvertor: fastjson
      valueEncoder: kryo
      valueDecoder: kryo
      poolConfig:
        minIdle: 10
        maxIdle: 50
        maxTotal: 200
      host: ${redis.host}
      port: ${redis.port}
   password: ${redis.password}

配置项

jetcache.statIntervalMinutes 0 统计间隔,0表示不统计
jetcache.areaInCacheName true

jetcache-anno把cacheName作为远程缓存key前缀,2.4.3以前的版本总是把areaName加在cacheName中,因此areaName也出现在key前缀中。

2.4.4以后可以配置,为了保持远程key兼容默认值为true,但是新项目的话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.local.${area}.expireAfterAccessInMillis 0 需要jetcache2.2以上,以毫秒为单位,指定多长时间没有访问,就让缓存失效,当前只有本地缓存支持。0表示不使用这个功能。

2.4 使用注解启用功能

public interface UserService {
    @Cached(name="userCache.", key="#userId", localExpire=300, expire = 600, cacheType=CacheType.BOTH)
    @CacheRefresh(refresh = 100, stopRefreshAfterLastAccess = 1800, refreshLockTimeout=10 )
    @CachePenetrationProtecct
    User getUserById(long userId);
}

@Cached注解

area “default” 如果在配置中配置了多个缓存area,在这里指定使用哪个area
name 未定义 指定缓存的唯一名称,不是必须的,如果没有指定,会使用类名+方法名。name会被用于远程缓存的key前缀。另外在统计中,一个简短有意义的名字会提高可读性。
key 未定义 使用SpEL指定key,如果没有指定会根据所有参数自动生成。
expire 未定义 超时时间。如果注解上没有定义,会使用全局配置,如果此时全局配置也没有定义,则为无穷大
timeUnit TimeUnit.SECONDS 指定expire的单位
cacheType CacheType.REMOTE 缓存的类型,包括CacheType.REMOTE、CacheType.LOCAL、CacheType.BOTH。如果定义为BOTH,会使用LOCAL和REMOTE组合成两级缓存
localLimit 未定义 如果cacheType为LOCAL或BOTH,这个参数指定本地缓存的最大元素数量,以控制内存占用。如果注解上没有定义,会使用全局配置,如果此时全局配置也没有定义,则为100
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指定条件,如果表达式返回true的时候才去缓存中查询
postCondition 未定义 使用SpEL指定条件,如果表达式返回true的时候才更新缓存,该评估在方法执行后进行,因此可以访问到#result

@CacheRefresh注解

refresh 未定义 刷新间隔
timeUnit TimeUnit.SECONDS 时间单位
stopRefreshAfterLastAccess 未定义 指定该key多长时间没有访问就停止刷新,如果不指定会一直刷新
refreshLockTimeout 60秒 类型为BOTH/REMOTE的缓存刷新时,同时只会有一台服务器在刷新,这台服务器会在远程缓存放置一个分布式锁,此配置指定该锁的超时时间

@CachePenetrationProtect注解

当缓存访问未命中的情况下,对并发进行的加载行为进行保护。 当前版本实现的是单JVM内的保护,即同一个JVM中同一个key只有一个线程去加载,其它线程等待结果

发表评论 / Comment

用心评论~