一、概述
二、在Windows10 安装Redis
下载:Redis 3.0.504
提取码:a87q
1、下载文件到D盘,解压放在新创建Redis文件下
2、打开cmd,切换到目录D:\Redis
redis-server.exe redis.windows.conf
3、打开另一个cmd,切换到 redis 目录下运行
redis-cli.exe -h 127.0.0.1 -p 6379
设置键值对:
set key aaa
取出键值对:
get key
4、密码操作
配置文件修改:打开redis.conf或redis.windows.conf(如果没有此文件,需下载),放到Redis目录下,找到requirepass值修改密码
# requirepass foobared
requirepass yourpassword //此处注意,行前不能有空格
重新设置密码后,重新登录才能获取操作权限
redis-cli.exe -h 127.0.0.1 -p 6379 -a 123 //需添加密码参数
三、IDEA使用Redis
1、 在pom.xml引入依赖
<!-- springboot整合redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2、在application.properties 配置Redis
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=123
上述两个步骤完成后,SpringBoot自动在Spring容器中配置一个redisTemplate的Bean,所以可以直接使用redisTemplate
3、实现Redis
@Autowired
private RedisTemplate<String,Object> redisTemplate;
public List<Student> getAllStudent() {
//查询缓存
List<Student> studentList= (List<Student>)redisTemplate.opsForValue().get("allStudents");
if(null == studentList) {
//缓存为空,查询一遍数据库
studentList = studentMapper.selectAllStudent();
//把数据库查询出来数据,放入Redis中
redisTemplate.opsForValue().set("allStudents",studentList);
}
return studentList;
}
同时实体类要实现序列化,不然运行后会抛出异常
字符串序列化器,让缓存中的key由序列转为较直观的字符串:
RedisSerializer redisSerializer = new StringRedisSerializer();
redisTemplate.setStringSerializer(redisSerializer);
四、产生问题
高并发条件下,可能会有问题,即缓存穿透(大量的人同时调用底层的数据库)
解决:
第一种方法:在方法上添加synchronized
@Override
public synchronized List<Student> getAllStudent() {
...
}
第二个方法:
@Override
public /*synchronized*/ List<Student> getAllStudent() {
//字符串序列化器
RedisSerializer redisSerializer = new StringRedisSerializer();
redisTemplate.setStringSerializer(redisSerializer);
//高并发条件下,可能发生 缓存穿透(大量的人同时调用底层的数据库)
//查询缓存
List<Student> studentList= (List<Student>)redisTemplate.opsForValue().get("allStudents");
//双重检测锁
if(null == studentList) {
synchronized (this) {
//再从redis获取一下
studentList= (List<Student>)redisTemplate.opsForValue().get("allStudents");
if(null == studentList) {
System.out.println("查询数据库。。");
//缓存为空,查询一遍数据库
studentList = studentMapper.selectAllStudent();
//把数据库查询出来数据,放入Redis中
redisTemplate.opsForValue().set("allStudents",studentList);
} else {
System.out.println("查询缓存。。");
}
}
} else {
System.out.println("查询缓存。。");
}
return studentList;
}
测试:
@GetMapping("students")
public Object students() {
Runnable runnable = new Runnable() {
@Override
public void run() {
studentService.getAllStudent();
}
};
//多线程测试缓存穿透问题
ExecutorService executorService = Executors.newFixedThreadPool(25);
for (int i = 0; i < 10000; i++) {
executorService.submit(runnable);
}
return studentService.getAllStudent();
}
注意:
运行程序之前,要先清除redis缓存