一、缓存
1、什么是缓存?
在互联网场景下,尤其 2C 端大流量场景下,需要将一些经常展现和不会频繁变更的数据,存放在存取速率更快的地方。缓存就是一个存储器,在技术选型中,常用 Redis 作为缓存数据库。缓存主要是在获取资源方便性能优化的关键方面。
Redis 是一个高性能的 key-value 数据库,支持多种数据类型, redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。
2、缓存的作用
缓存在不同场景下作用不一样
操作系统磁盘缓存=====>减少磁盘机械操作
数据库缓存=====>减少对数据库的查询
Web服务器缓存=====>减少对应用服务器的请求。
客户端浏览器缓存=====>减少对网站的访问。
二、SpringBoot整合Redis作为缓存
开启SpringBoot的缓存
导入缓存启动器和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>
在SpringBoot启动类上开启缓存的注解
@EnableCaching //开启缓存
@SpringBootApplication
public class SpringbootCacheApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootCacheApplication.class, args);
}
}
看看Redis的缓存是否生效
来到CacheAutoConfiguration这里导入了一个CacheConfigurationImportSelector
打开这个CacheConfigurationImportSelector,这里去获取了一些配置类,但是他获取了哪些配置类呢?可以打个断点看一下。
CacheConfigurationImportSelector去获取了这些配置类,这些配置类有哪些是生效的呢?在配置文件中加入 debug=true 查看哪些配置类生效了
查询RedisCacheConfiguration这个配置类是生效的,说明redis缓存配置成功。
然后查看其他配置类是无生效的,
开始测试
在配置文件中添加redis的主机地址,端口默认6379
由于RedisTemplate默认是使用JDK的序列化方式,存到redis时会乱码,所以需要自定义一个RedisTemplate
@Bean
@SuppressWarnings("all")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<String,
Object>();
template.setConnectionFactory(factory);
// Json序列化配置
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);
// String 的序列化
StringRedisSerializer stringRedisSerializer = new
StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
测试方法
@Cacheable(cacheNames = "emp",key = "#id")
public Employee getEmp(Integer id){
System.out.println("查询的员工ID:" +id);
return employeeMapper.getEmpById(id);
}
执行方法
第一次,执行了sql语句
第二次查询就使用了redis的缓存
查询发现key序列化了,但是value没有被序列化,但是查出的数据又是正常的Json数据,这时就需要自定义一个CacheManager
自定义CacheManager(注意:1.0和2.0版本,有较大差距,以下是基于2.0版本的)
@Bean
public CacheManager DiyCacheManager(RedisConnectionFactory factory){
RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofDays(1)) //设置默认超过期时间是1天
.disableCachingNullValues()
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));//设置序列化方式
return RedisCacheManager.builder(factory).cacheDefaults(cacheConfiguration).build();
}
自定义CacheManager之后,再次测试发现value已经正常序列化为Json数据了
到这里SpringBoot整合redis作为缓存就完成了,它的执行原理和SpringBoot的自动配置原理类似,可以看我的另外一篇博客SpringBoot扩展SpringMVC原理和全面接管SpringMVC配置原理是差不多的,都是一通百通了。
结论: SpringBoot整合redis作为缓存,主要就是Redis的序列化问题,需要自定义RedisTemplate和CacheManager 如果没有自定义这个就会出现key和value乱码问题!