缓存雪崩

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qmqm011/article/details/88850102

一、什么是缓存雪崩

当缓存服务器宕机或者在某一个时间段大量缓存集中失效,这时所有的请求都直接查询后端数据库,给数据库造成极大的压力甚至是宕机,从而引起应用服务器雪崩。

二、缓存雪崩的解决方案

对于缓存服务宕机造成的缓存雪崩,可以采用高可用的缓存架构,比如Redis哨兵或者Cluster。

对于大量缓存同时失效造成的缓存雪崩,有以下解决方案:

1、对缓存的过期时间加一个随机数

可以在原有的失效时间基础上增加一个随机数,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。

2、加锁排队

在缓存失效后,通过加锁(分布式锁)或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。

public class Test {

    @Autowired
    private RedisTemplate redisTemplate;

    public Object get(String key) {
        // 先从缓存查询
        Object value = redisTemplate.opsForValue().get(key);
        // 缓存查询到数据直接返回
        if (value != null) {
            return value;
        } else {
            // 缓存没有查询到数据,则进行加锁
            if (lock(key)) {
                // 获取锁成功后,再次查询缓存,进行双重检查
                value = redisTemplate.opsForValue().get(key);
                if (value == null) {
                    // 查询数据库,并设置到缓存中
                    value = queryDB(key);
                    redisTemplate.opsForValue().set(key, value);
                }
                // 释放锁
                unlock(key);
                return value;
            } else {
                // 获取锁失败,说明其他线程先获取到锁,再次从缓存查询
                return get(key);
            }
        }
    }

    // 查询数据库
    private Object queryDB(String key) {
        return new Object();
    }

    // 加锁,使用Redis或Zookeeper实现分布式锁
    public boolean lock(String key) {
        return true;
    }

    // 释放锁
    public void unlock(String key) {

    }

}

3、热点数据永不过期

对于热点数据,可以设置为永不过期。

4、服务降级和熔断

如果访问量超过一定阈值,则对后续的请求执行快速失败。如果某些服务不可用,也执行快速失败,防止大量请求阻塞拖垮应用。

猜你喜欢

转载自blog.csdn.net/qmqm011/article/details/88850102