缓存击穿:缓存中没有数据(或者数据已过期)但是数据库中有
在高并发下,为了避免请求直接打到数据库,可以使用双重检查锁的方式进行数据库查询
具体步骤如下:
-
- 先查 reids 中是否有数据
-
- 如果 redis 中没有数据,使用 synchronized 进行加锁
-
- 再次查询 reids 中是否有数据
-
- 如果第3步查询还是没有数据,此时再查数据库
-
- 查询到数据库中的数据后,将数据写入到redis中
public User selectUser(Integer id) {
// 第1步,先查redis
User user = (User) redisTemplate.opsForValue().get(CACHE_KEY_USER + id);
if (user == null) {
// 第2步,对于高QPS,先加锁,保证一个请求操作,让外面的查询等待一下,避免击穿mysql
synchronized (UserServiceImpl.class) {
// 第3步,二次查redis,如果还是null,可以去查mysql了
user = (User) redisTemplate.opsForValue().get(CACHE_KEY_USER + id);
if (user == null) {
// 第4步,查询mysql
user = userMapper.selectById(id);
if (user != null) {
// 第5步,将数据写入到redis
redisTemplate.opsForValue().setIfAbsent(CACHE_KEY_USER + user.getId(), user, 7L, TimeUnit.DAYS);
}
}
}
}
return user;
}
使用双重检查锁的方法,可以避免高并发情况下,所有请求直接打到数据库上