使用双重检查锁避免Redis缓存击穿

751 阅读1分钟

缓存击穿:缓存中没有数据(或者数据已过期)但是数据库中有

在高并发下,为了避免请求直接打到数据库,可以使用双重检查锁的方式进行数据库查询

具体步骤如下:

    1. 先查 reids 中是否有数据
    1. 如果 redis 中没有数据,使用 synchronized 进行加锁
    1. 再次查询 reids 中是否有数据
    1. 如果第3步查询还是没有数据,此时再查数据库
    1. 查询到数据库中的数据后,将数据写入到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;
}

使用双重检查锁的方法,可以避免高并发情况下,所有请求直接打到数据库上