阿里开源的缓存框架JetCache,实现spring二级缓存

您所在的位置:网站首页 mybatis的两级缓存区别 阿里开源的缓存框架JetCache,实现spring二级缓存

阿里开源的缓存框架JetCache,实现spring二级缓存

2023-09-24 02:23| 来源: 网络整理| 查看: 265

之前一直在用Spring Cache进行接口数据的缓存,主要是Spring Cache在对具体key缓存失效时间的设置不是很方法,还要自己去扩展,无意中发现了阿里的JetCache。大部分的需求都能满足,并且有一些很实用的功能,今天给大家介绍下。

JetCache是一个基于Java的缓存系统封装,提供统一的API和注解来简化缓存的使用。 JetCache提供了比SpringCache更加强大的注解,可以原生的支持TTL、两级缓存、分布式自动刷新,还提供了Cache接口用于手工缓存操作。 当前有四个实现,RedisCache、TairCache(此部分未在github开源)、CaffeineCache(in memory)和一个简易的LinkedHashMapCache(in memory),要添加新的实现也是非常简单的。

GitHub:https://github.com/alibaba/jetcache 在这里插入图片描述

简介

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支持 要求

JetCache需要JDK1.8、Spring Framework4.0.8以上版本。Spring Boot为可选,需要1.1.9以上版本。如果不使用注解(仅使用jetcache-core),Spring Framework也是可选的,此时使用方式与Guava/Caffeine cache类似。

文档目录 快速入门基本Cache API通过@CreateCache注解创建Cache实例通过注解实现方法缓存配置详解高级Cache APIRedis支持(两种redis客户端二选一即可) 使用jedis客户端连接redis使用lettuce客户端连接redis 内存缓存LinkedHashMapCache和CaffeineCache统计Builder:未使用Spring4(或未使用Spring)的时候,或通过Builder手工构造Cache开发者文档升级和兼容性指南FAQ 基本配置(使用Spring Boot)

如果使用Spring Boot,可以按如下的方式配置(这里使用了jedis客户端连接redis,如果需要集群、读写分离、异步等特性支持请使用lettuce客户端)。

增加Maven配置:

com.alicp.jetcache jetcache-starter-redis 2.5.14 配置说明 jetcache: statIntervalMinutes: 15 areaInCacheName: false hidePackages: com.alibaba local: default: type: caffeine limit: 100 keyConvertor: fastjson expireAfterWriteInMillis: 100000 otherArea: type: linkedhashmap limit: 100 keyConvertor: none expireAfterWriteInMillis: 100000 remote: default: type: redis keyConvertor: fastjson valueEncoder: java valueDecoder: java poolConfig: minIdle: 5 maxIdle: 20 maxTotal: 50 host: ${redis.host} port: ${redis.port} otherArea: type: redis keyConvertor: fastjson valueEncoder: kryo valueDecoder: kryo poolConfig: minIdle: 5 maxIdle: 20 maxTotal: 50 host: ${redis.host} port: ${redis.port}

配置通用说明如下

属性默认值说明jetcache.statIntervalMinutes0统计间隔,0表示不统计jetcache.areaInCacheNametruejetcache-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。方法缓存必须指定keyConvertorjetcache.[local|remote].${area}.valueEncoderjava序列化器的全局配置。仅remote类型的缓存需要指定,可选java和kryojetcache.[local|remote].${area}.valueDecoderjava序列化器的全局配置。仅remote类型的缓存需要指定,可选java和kryojetcache.[local|remote].${area}.limit100每个缓存实例的最大元素的全局配置,仅local类型的缓存需要指定。注意是每个缓存实例的限制,而不是全部,比如这里指定100,然后用@CreateCache创建了两个缓存实例(并且注解上没有设置localLimit属性),那么每个缓存实例的限制都是100jetcache.[local|remote].${area}.expireAfterWriteInMillis无穷大以毫秒为单位指定超时时间的全局配置(以前为defaultExpireInMillis)jetcache.local.${area}.expireAfterAccessInMillis0需要jetcache2.2以上,以毫秒为单位,指定多长时间没有访问,就让缓存失效,当前只有本地缓存支持。0表示不使用这个功能。

上表中${area}对应@Cached和@CreateCache的area属性。注意如果注解上没有指定area,默认值是"default"。

关于缓存的超时时间,有多个地方指定,澄清说明一下:

put等方法上指定了超时时间,则以此时间为准put等方法上未指定超时时间,使用Cache实例的默认超时时间Cache实例的默认超时时间,通过在@CreateCache和@Cached上的expire属性指定,如果没有指定,使用yml中定义的全局配置,例如@Cached(cacheType=local)使用jetcache.local.default.expireAfterWriteInMillis,如果仍未指定则是无穷大

启动类开启缓存:

@SpringBootApplication @EnableMethodCache(basePackages = "com.cxytiandi.jetcache") @EnableCreateCacheAnnotation public class App { public static void main(String[] args) { SpringApplication.run(App.class); } } @EnableMethodCache 用于激活@Cached注解的使用@EnableCreateCacheAnnotation 用于激活@CreateCache注解的使用

定义一个简单的实体类来作为数据的缓存,必须实现Serializable接口。

@Data public class User implements Serializable { private Long id; private String name; } 通过注解实现方法缓存 @CreateCache使用 @CreateCache(expire = 100) private Cache userCache; User user = new User(); user.setId(1L); user.setName("yinjihuan"); // 新增缓存 userCache.put(1L, user); // 删除缓存 userCache.remove(1L);

用起来很简单,就像操作本地Map一样,@CreateCache中有很多配置需要我们自己去指定,不指定则使用默认的,关于配置请查看文档:https://github.com/alibaba/jetcache/wiki/CreateCache_CN

@Cached使用 @Cached(name="getUser.", key="#id", expire = 8, cacheType=CacheType.BOTH) @Override public User getUser(Long id) { User user = new User(); user.setId(1L); user.setName("yinjihuan"); return user; } name 缓存名称key 缓存key,追加到name后面构成唯一的缓存key, 使用SpEL指定key,如果没有指定会根据所有参数自动生成。expire 缓存失效时间cacheType 缓存的类型,包括CacheType.REMOTE、CacheType.LOCAL、CacheType.BOTH。如果定义为BOTH,会使用LOCAL和REMOTE组合成两级缓存

更多配置的介绍请查看文档:https://github.com/alibaba/jetcache/wiki/MethodCache_CN

今天的介绍就到这里,使用起来还是很方便的,关于更多的功能大家自行去尝试吧,比如缓存定时刷新,缓存命中率统计,自定义序列化方式等等。

@Cached定义在接口上的坑 还有一个呢就是@Cached如果定义在接口上就不能指定key属性,框架中会自动根据参数生成key, 如果非得自己用SPEL表达式指定key的话,项目编译设置target必须为1.8格式,并且指定javac的-parameters参数,否则就要使用key="args[0]"这样按下标访问的形式。我建议还是把@Cached的定义放在实现类上,也方便修改。

CacheManager

使用CacheManager可以创建Cache实例,area和name相同的情况下,它和Cached注解使用同一个Cache实例。

注意:在jetcache 2.7 版本CreateCache注解已经废弃,请改用CacheManager.getOrCreateCache(QuickConfig)

例子:

@Autowired private CacheManager cacheManager; private Cache userCache; @PostConstruct public void init() { QuickConfig qc = QuickConfig.newBuilder("userCache") .expire(Duration.ofSeconds(100)) .cacheType(CacheType.BOTH) // two level cache .syncLocal(true) // invalidate local cache in all jvm process after update .build(); userCache = cacheManager.getOrCreateCache(qc); }

JetCache方法缓存和SpringCache比较类似,它原生提供了TTL支持,以保证最终一致,并且支持二级缓存。JetCache2.4以后支持基于注解的缓存更新和删除。

在spring环境下,使用@Cached注解可以为一个方法添加缓存,@CacheUpdate用于更新缓存,@CacheInvalidate用于移除缓存元素。注解可以加在接口上也可以加在类上,加注解的类必须是一个spring bean,例如:

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); }

key使用Spring的SpEL脚本来指定。如果要使用参数名(比如这里的key=“#userId”),项目编译设置target必须为1.8格式,并且指定javac的-parameters参数,否则就要使用key="args[0]"这样按下标访问的形式。

@CacheUpdate和@CacheInvalidate的name和area属性必须和@Cached相同,name属性还会用做cache的key前缀。

@CacheRefresh注解说明: 属性默认值说明refresh未定义刷新间隔timeUnitTimeUnit.SECONDS时间单位stopRefreshAfterLastAccess未定义指定该key多长时间没有访问就停止刷新,如果不指定会一直刷新refreshLockTimeout60秒类型为BOTH/REMOTE的缓存刷新时,同时只会有一台服务器在刷新,这台服务器会在远程缓存放置一个分布式锁,此配置指定该锁的超时时间 @CachePenetrationProtect注解:

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

参考

通过注解实现方法缓存

依赖哪个jar?

jetcache-anno-api:定义jetcache的注解和常量,不传递依赖。如果你想把Cached注解加到接口上,又不希望你的接口jar传递太多依赖,可以让接口jar依赖jetcache-anno-api。 jetcache-core:核心api,完全通过编程来配置操作Cache,不依赖Spring。两个内存中的缓存实现LinkedHashMapCache和CaffeineCache也由它提供。 jetcache-anno:基于Spring提供@Cached和@CreateCache注解支持。 jetcache-redis:使用jedis提供Redis支持。 jetcache-redis-lettuce(需要JetCache2.3以上版本):使用lettuce提供Redis支持,实现了JetCache异步访问缓存的的接口。 jetcache-starter-redis:Spring Boot方式的Starter,基于Jedis。 jetcache-starter-redis-lettuce(需要JetCache2.3以上版本):Spring Boot方式的Starter,基于Lettuce。

实战的哪些坑 再微服务环境下,每个服务有多个节点,如果是单单的多级缓存,一个节点更新了本地缓存,其他节点的本地缓存怎么办? JetCache的解决方案是,使用 redis的发布订阅(Pub/Sub)功能。 埋坑就在这 Redis的Pub Sub在redis server瞬时启动、停机、重启时订阅的消息均会丢失,且在消费失败时无法重复获取消息,会导致缓存不一致,还会存在客户端掉线,中间的休息就丢了,客户端消息积累等问题,所以内置的不满足需求,BroadcastManager可以自己更换的,比如换成使用专门的消息队列,即便如此,也很难保证强一致,一个简单的办法是把本地缓存的超时时间弄短点。

更换文件 SpringConfigProvider -> doInit -> initCacheMonitorInstallers 2. 只有远程服务才有 多节点本地缓存自动刷新功能。

NotifyMonitorInstaller 在这里插入图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3