整合Springboot开发
第一步:加入相关依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
第二步:写配置
(可以直接使用,只需要配置加入redis作为缓存,CacheAutoConfiguration-> RedisCachConfiguration->自动配置了RedisCacheManager->初始化所有的缓存->每个缓存决定使用什么配置->如果RedisCachConfiguration有就用己有的,没有就用默认配置->想修改缓存配置只需要给容器中放入一个RedisCachConfiguratio->就会应用到当前的RedisCacheManager管理的所有缓存分区中)
**自定义缓存管理器(将缓存保存为json格式),给容器中放入RedisCachConfiguratio **:
@EnableConfigurationProperties(CacheProperties.class)//将配置文件中的配置生效
@Configuration
@EnableCaching
public class redisCacheConfiguration {
@Bean
RedisCacheConfiguration redisCacheConfigurationInit(CacheProperties cacheProperties) {
//得到默认配置
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
config = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.string()));
//配置JSON格式作为缓存数据
config = config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
//配置redis缓存格式
CacheProperties.Redis redisProperties = cacheProperties.getRedis();
if (redisProperties.getTimeToLive() != null) {
config = config.entryTtl(redisProperties.getTimeToLive());
}
if (redisProperties.getKeyPrefix() != null) {
config = config.prefixKeysWith(redisProperties.getKeyPrefix());
}
if (!redisProperties.isCacheNullValues()) {
config = config.disableCachingNullValues();
}
if (!redisProperties.isUseKeyPrefix()) {
config = config.disableKeyPrefix();
}
return config;
}
}
・
application.properties
・
spring.cache.type=redis
spring.cache.redis.key-prefix=CACHE //指定缓存Key的前缀名,没指定就默认使用缓存名作为前缀
spring.cache.redis.use-key-prefix=true //是否使用前缀
spring.cache.redis.cache-null-values=true //是否缓存空值,防止缓存穿透
spring.cache.redis.time-to-live=3600000 //设置缓存存活时间,时间单位毫秒
・
第三步开启缓存,@EnableCaching,主启动类开启缓存
・
@EnableCaching
@EnableFeignClients(basePackages = "com.atguigu.gulimail.product.feign")
@EnableDiscoveryClient
@MapperScan("com.atguigu.gulimail.product.dao")
@SpringBootApplication
public class GulimailProductApplication {
public static void main(String[] args) {
SpringApplication.run(GulimailProductApplication.class, args);
}
}
・
SpringCache 缓存注解
・
(1)@CacheConfig: 主要用于配置该类中会用到的一些共用的缓存配置
・
・
(2)@Cacheable: 主要方法返回值加入缓存。同时在查询时,会先从缓存中取,若不存在才再发起对数据库的访问。,需要指定要放到那个名字的缓存(缓存的分区)。
@Cacheable(value = “category”,key = “#root.methodName”) ,value 指定缓存的分区名字,,key = “#root.methodName” 指定key的名称为当前方法名
@Cacheable(value = "category",key = "#root.methodName")
@Override
public List<CategoryEntity> getLeve1Categorys() {
List<CategoryEntity> entities = baseMapper.selectList(new QueryWrapper<CategoryEntity>().eq("parent_cid", 0));
return entities;
}
・
・
(3)@CachePut:配置于函数上,能够根据参数定义条件进行缓存,与@Cacheable不同的是,每次回真实调用函数,所以主要用于数据新增和修改操作上。
・
/** * 添加tasklog * @param tasklog * @return */
@CachePut(value = CACHE_KEY, key = "#tasklog.id")
public Tasklog create(Tasklog tasklog){
System.out.println("CREATE");
System.err.println (tasklog);
taskLogMapper.insert(tasklog);
return tasklog;
}
(4)@CacheEvict:配置于函数上,通常用在删除方法上,用来从缓存中移除对应数据
・
・
@CacheEvict(value = "category",allEntries = true)
@Transactional
@Override
public void updateCascade(CategoryEntity category) {
this.updateById(category);
categoryBrandRelationService.updateCategory(category.getCatId(),category.getName());
}
・
(5)@Caching:配置于函数上,组合多个Cache注解使用。
・
・
@Caching(evict = {
//删除缓存注解
@CacheEvict(value = "category",key = "'getLeve1Categorys'"),
@CacheEvict(value = "category",key = "'getCatalogJson'")
})
@Transactional
@Override
public void updateCascade(CategoryEntity category) {
this.updateById(category);
categoryBrandRelationService.updateCategory(category.getCatId(),category.getName());
}
・
・
・
SpringCache 读模式下缓存问题的解决
缓存穿透:
缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求(查询到一个NULL数据)
解决:缓存空数据:spring.cache.redis.cache-null-values=true
・
・
缓存击穿:
缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。
解决:加锁 在@Cacheable()中设置@Cacheable(sync=true)本地锁解决击穿
缓存雪崩:
缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。(大量Key同时过期),和缓存击穿不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。
解决:指定过期时间:spring.cache.redis.time-to-live=3600000