Cache-让你的代码更香-缓存注解的最佳通常-Spring (cache文件夹可以删除吗)
作者最近在开发公司名目时经常使用到缓存,并在翻看先人代码时,看到了一种关于@Cacheable注解的自定义缓存有效期的处置打算,觉得比拟适用,因此作者自己拓展完善了一番后分享给各位。
Spring缓存惯例性能
SpringCache框架给咱们提供了@Cacheable注解用于缓存方法前往内容。然而@Cacheable注解不能定义缓存有效期。这样的话在一些须要自定义缓存有效期的场景就不太适用。
依照SpringCache框架给咱们提供的RedisCacheManager成功,只能在全局设置缓存有效期。这里给大家看一个惯例的CacheConfig缓存性能类,代码如下,
@EnableCaching@ConfigurationpublicclassCacheConfigextendsCachingConfigurerSupport{...privateRedisSerializer<String>keySerializer(){returnnewStringRedisSerializer();}privateRedisSerializer<Object>valueSerializer(){returnnewGenericFastJsonRedisSerializer();}publicstaticfinalStringCACHE_PREFIX="crowd:";@BeanpublicCacheManagercacheManager(RedisConnectionFactoryredisConnectionFactory){//性能序列化(处置乱码的疑问)RedisCacheConfigurationconfig=RedisCacheConfiguration.defaultCacheConfig()//设置key为String.serializeKeysWith(RedisSerializationContext.SerializationPr.fromSerializer(keySerializer()))//设置value为智能转Json的Object.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer())).computePrefixWith(name->CACHE_PREFIX+name+":").entryTtl(Duration.ofSeconds(600));RedisCacheWriterredisCacheWriter=RedisCacheWriter.nonLockingRedisCacheWriter(Objects.requireNonNull(redisConnectionFactory));returnnewRedisCacheManager(redisCacheWriter,config);}}
这外面繁难对RedisCacheConfiguration缓存性能做一下说明:
那么经常使用如上性能生成的Redis缓存key称号是什么样得嘞?这里用开源名目crowd-admin的ConfigServiceImpl类下getValueByKey(Stringkey)方法举例,
@Cacheable(value="configCache",key="#root.methodName+'_'+#root.args[0]")@OverridepublicStringgetValueByKey(Stringkey){QueryWrer<Config>wrapper=newQueryWrapper<>();wrapper.eq("configKey",key);Configconfig=getOne(wrapper);if(config==null){returnnull;}returnconfig.getConfigValue();}
口头此方法后,Redis中缓存key称号如下,
图片
TTL过时期间是287,跟咱们全局设置的300秒基本是分歧的。此时假设咱们想把getValueByKey方法的缓存有效期独自设置为600秒,那咱们该如何操作嘞?
@Cacheable注解自动是没有提供无关缓存有效期设置的。想要独自修正getValueByKey方法的缓存有效期只能修正全局的缓存有效期。那么有没有别的方法能够为getValueByKey方法独自设置缓存有效期嘞?当然是有的,大家请往下看。
自定义MyRedisCacheManager缓存
其实咱们可以经过自定义MyRedisCacheManager类承袭SpringCache提供的RedisCacheManager类后,重写createRedisCache(Stringname,RedisCacheConfigurationcacheConfig)方法,代码如下,
publicclassMyRedisCacheManagerextendsRedisCacheManager{publicMyRedisCacheManager(RedisCacheWritercacheWriter,RedisCacheConfigurationdefaultCacheConfiguration){super(cacheWriter,defaultCacheConfiguration);}@OverrideprotectedRedisCachecreateRedisCache(Stringname,RedisCacheConfigurationcacheConfig){String[]array=StringUtils.split(name,"#");name=array[0];//解析@Cacheable注解的value属性用以独自设置有效期if(array.length>1){longttl=Long.parseLong(array[1]);cacheConfig=cacheConfig.entryTtl(Duration.ofSeconds(ttl));}returnsuper.createRedisCache(name,cacheConfig);}}
MyRedisCacheManager类逻辑如下,
接着咱们修正下CacheConfig类的cacheManager方法用以经常使用MyRedisCacheManager类。代码如下,
@BeanpublicCacheManagercacheManager(RedisConnectionFactoryredisConnectionFactory){returnnewMyRedisCacheManager(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory),defaultCacheConfig());}privateRedisCacheConfigurationdefaultCacheConfig(){returnRedisCacheConfiguration.defaultCacheConfig().serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer())).serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer())).computePrefixWith(name->CACHE_PREFIX+name+":").entryTtl(Duration.ofSeconds(600));}
最后咱们修正下@Cacheable注解经常使用形式,在原有value属性的configCache值后参与#600,独自标识缓存有效期。代码如下,
@Cacheable(value="configCache#600",key="#root.methodName+'_'+#root.args[0]")@OverridepublicStringgetValueByKey(Stringkey){...}
看下getValueByKey方法生成的Redis缓存key有效期是多久。如下,
图片
OK,看到是590秒有效期后,咱们就功败垂成了,宿愿本文能对大家有所协助
Spring本地缓存的使用方法
我们现在在用的Spring Cache,可以直接看Spring Boot提供的缓存枚举类,有如下这些:
EhCache:一个纯Java的进程内缓存框架,所以也是基于本地缓存的。(注意EhCache2.x和EhCache3.x相互不兼容)。 Redis:分布式缓存,只有Client-Server(C\S)模式,Java一般使用Jedis/Luttuce来操纵。 Hazelcast:基于内存的数据网格。虽然它基于内存,但是分布式应用程序可以使用Hazelcast进行分布式缓存、同步、集群、处理、发布/订阅消息等。 Guava:它是Google Guava工具包中的一个非常方便易用的本地化缓存实现,基于LRU(最近最少使用)算法实现,支持多种缓存过期策略。在Spring5.X以后的版本已经将他标记为过期了。 Caffeine:是使用Java8对Guava缓存的重写版本,在Spring5中将取代了Guava,支持多种缓存过期策略。 SIMPLE:使用ConcurrentMapCacheManager,因为不支持缓存过期时间,所以做本地缓存基本不考虑该方式。
关于分布式缓存,我们需要后面会专门讨论Redis的用法,这里只看本地缓存。性能从高到低,依次是Caffeine,Guava,ConcurrentMapCacheManager,其中Caffeine在读写上都快了Guava近一倍。
这里我们只讨论在Spring Boot里面怎么整合使用Caffeine和EhCache。
主要有以下几个步骤:
1)加依赖包:
2)配置缓存: 这里有两种方法,通过文件配置或者在配置类里面配置,先看一下文件配置,我们可以写一个properties文件,内容像这样:
然后还要在主类中加上@EnableCaching注解:
另外一种更灵活的方法是在配置类中配置:
应用类:
测试类:
导入依赖包,分为2.x版本和3.x版本。 其中2.x版本做如下导入:
3.x版本做如下导入:
导包完成后,我们使用JCacheManagerFactoryBean + 的方式配置:
参考资料:
spring@cacheable查询很慢
题主是想询问“spring@cacheable查询很慢的原因”,原因是:1、缓存策略不当:缓存策略的选择直接影响到缓存的效率,如果选择的策略不当,例如缓存时间过长或者缓存的数据量过大,会导致缓存效率低下,反而降低了系统性能。 建议根据具体业务需求选择合适的缓存策略。 2、缓存命中率低:命中率低即缓存中没有需要查找的数据,需要重新查询数据库,这样就会导致查询速度慢。 建议在使用@Cacheable注解时,设置合适的缓存Key,保证缓存命中率。 3、缓存数据量过大:如果缓存数据量过大,会导致缓存的查找和更新效率降低,建议对缓存进行分段管理,分别缓存不同区间的数据,减小缓存数据量。 4、缓存服务器性能问题:如果缓存服务器性能较差,也会导致查询缓存数据较慢,建议对缓存服务器进行优化或更换性能更好的服务器。
免责声明:本文转载或采集自网络,版权归原作者所有。本网站刊发此文旨在传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及版权、内容等问题,请联系本网,我们将在第一时间删除。同时,本网站不对所刊发内容的准确性、真实性、完整性、及时性、原创性等进行保证,请读者仅作参考,并请自行核实相关内容。对于因使用或依赖本文内容所产生的任何直接或间接损失,本网站不承担任何责任。