SpringBoot 集成 redis
1.在pom.xml文件中配置redis的相关依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2.在SpringBoot 的配置文件application中添加redis配置
spring.redis.host=127.0.0.1
#Redis服务器连接端口
spring.redis.port=6379
#Redis服务器连接密码(默认为空)
spring.redis.password=
#连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=8
#连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
#连接池中的最大空闲连接
spring.redis.pool.max-idle=8
#连接池中的最小空闲连接
spring.redis.pool.min-idle=0
#连接超时时间(毫秒)
spring.redis.timeout=30000
3.注入 RedisTemplate
配置完成 1 、2 步之后,SpringBoot就帮我们自动配置了 RedisTemplate 这个redis模板类了。只需在需要操作redis的类中注入 RedisTemplate:
@Autowired
private RedisTemplate<String,String> redisTemplate;
@Autowired
private RedisTemplate<Object,Object> redisTemplate;
注意: 1.SpringBoot帮我们注入的 RedisTemplate 类,泛型只能写<String,String> 、<Object,Object>
2.实体类需要 实现 Serializer 类。才能进行序列化的数据存储到 redis 中。
4.演示代码
public class StudentServiceImpl implements StudentService{
//注入 持久层 类 用于调动数据库
@Autowired
private StudentMapper studentMapper;
//注入 redis 提供的模板类(引入pom 配置好 application IOC中就会有这个类)
@Autuwired
private RedisTemplate<Object,Object> redisTemplate;
/**
获取学生列表的类
*/
public List<Student> getAllStudent(){
//1.设置序列化后的key能正常显示,而不是显示的序列化后似乱码的样式
//(1)RedisSerializer类是 redis的序列化器 StringRedisSerializer类 将结果序列化成可读性 //强的字符串的序列化信息。(字符串的序列化器)
RedisSerializer redisSerializer = new StringRedisSerializer();
//(2)设置字符串的序列化将 key 值序列化成字符串
redisTemplate.setKeySerializer(redisSerializer);
//查询缓存
List<Student> studentList = redisTemplate.opsForValue().get("allStudent");
//判断缓存中是否有 上述指定的 key "allStudent" 查询的数据。没有的话,则查询数据库
if(null == studentList){
//查询数据库
studentList = studentMapper.getAllStudent();
//将查询数据库得到的数据,存入缓存 redis 库中 set(key的名称,value值)
redisTemplate.opsForValue().set("allStudent",studentList);
}
return studentList;
}
}
(1) 上述代码的问题解析
在请求量很大的情况下(也就是高并发时),上述代码就有 "缓存穿透" 的问题产生了。
"缓存穿透": 就是说,在实际的场景中,我们预想的是 第一个人进行访问后,将数据存到 redis 中,接下来进来的人直接 读取 redis 缓存中的数据。但是在高并发的情况下,这种预想就有问题了。当并发在1W+ 或者更高的时候,第一次进来访问的人可能就不只是一个人了,所以就造成了很多人访问没有走缓存而是走的关系型数据库查询。这种情况就是"缓存穿透"。
解决方法:
方法一: 在方法上添加 线程锁 关键字 synchronized
public synchronized List<Student> getAllStudent(){}
方法二: 在代码逻辑中使用 双重锁机制:
public class StudentServiceImpl implements StudentService{
//注入 持久层 类 用于调动数据库
@Autowired
private StudentMapper studentMapper;
//注入 redis 提供的模板类(引入pom 配置好 application IOC中就会有这个类)
@Autuwired
private RedisTemplate<Object,Object> redisTemplate;
/**
获取学生列表的类
*/
public List<Student> getAllStudent(){
RedisSerializer redisSerializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(redisSerializer);
List<Student> studentList = redisTemplate.opsForValue().get("allStudent");
//双重检测锁
if(null == studentList){
studentList = redisTemplate.opsForValue().get("allStudent");
synchronized(this){
if(null == studentList){
studentList = studentMapper.getAllStudent();
redisTemplate.opsForValue().set("allStudent",studentList);
}
}
}
return studentList;
}
}