引入
在以前的模板中,总是以RedisTemplate redisTemplate ;形式注入到项目模块中。 但是做逻辑判断的时候,要人工的去写逻辑过程,比如①先去redis查,②没有再去数据库查, ③查到的数据放到缓存中。每次都要去写这样的逻辑显得代码实在是非常的拥挤和庞大 为了优化这一类的功能,spring框架引入了cache ,当和redis整合的时候,就让开发变得轻松,只关注业务。
构建
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.6.0</version>
</dependency>
yml
之前整合了redis配置,这里就直接配置cache
redis:
host: 192.168.182.128
port: 6379
cache:
type: redis
主启动类@EnableCaching //开启缓存 ,或者config类上加@EnableCaching ,让主启动类扫描到就可以了
使用 在你需要做缓存处理的方法上加注解:@Cacheable("<你的key>") ,这样你就不用写RedisTemplate 方法了
默认行为
- 缓存存在,则方法不调用
key 默认自动生成,缓存名字::SimpleKey [] - 过期时间
ttl = -1 - 缓存的值,默认生成
java序列化 ,序列化后存入到redis 中
自定义行为
- 指定生成缓存使用的
key - 指定缓存数据的存活时间 yml
time-to-live: 3600000 看你需求 - 将数据保存为
json 格式,方便其他接口兼容 自定义RedisCacheConfiguration
配置类
@Configuration
@EnableCaching
@EnableConfigurationProperties(CacheProperties.class)
public class RedisCacheConf {
@Bean
RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties){
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
config = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));
config = config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
CacheProperties.Redis propertiesRedis = cacheProperties.getRedis();
if(propertiesRedis.getTimeToLive()!=null){
config = config.entryTtl(propertiesRedis.getTimeToLive());
}
if(propertiesRedis.getKeyPrefix()!=null){
config = config.prefixKeysWith(propertiesRedis.getKeyPrefix());
}
if(propertiesRedis.isCacheNullValues()){
config = config.disableCachingNullValues();
}
if(propertiesRedis.isUseKeyPrefix()){
config = config.disableKeyPrefix();
}
return config;
}
}
可能有些项目这个配置类,会出现某些问题,可以替换下面的配置类,2个配置你自己选一个
配置类
@EnableCaching
@Configuration
@EnableConfigurationProperties(CacheProperties.class)
public class RedisConfig extends CachingConfigurerSupport {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
template.setConnectionFactory(factory);
template.setKeySerializer(redisSerializer);
template.setValueSerializer(jackson2JsonRedisSerializer);
template.setHashValueSerializer(jackson2JsonRedisSerializer);
return template;
}
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory,CacheProperties cacheProperties) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
CacheProperties.Redis propertiesRedis = cacheProperties.getRedis();
if(propertiesRedis.getTimeToLive()!=null){
config = config.entryTtl(propertiesRedis.getTimeToLive());
}
config = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer));
if(propertiesRedis.isCacheNullValues()){
config = config.disableCachingNullValues();
}
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
return cacheManager;
}
}
============================================================================================================================================================ spring-Cache的不足问题:
读模式:
- 缓存穿透:查询一个null值。解决:缓存空数据:配置yml
cache-null-values: true - 缓存击穿:大量并发进来同时查询一个正好过期的数据。解决:加锁,默认是无加锁,可以
@Cacheable(value = "<xxxxx>",sync = true) - 缓存雪崩:大量key同时过期,解决加随机时间,yml
time-to-live: 3600000 #1小时
写模式(缓存与数据库一致)
1.读写加锁 2. 引入Canal,感知到MySql的更新去更新数据库 3. 读多写多,直接去数据库查就可以了
常规数据,完全可以用使用spring-cache 特殊数据,另外设计
|