面试问题汇总缓存击穿、缓存失效、热点Key解决方案

缓存击穿、缓存失效、热点Key解决方案

缓存击穿: 查询一个数据库中不存在的数据,比如商品详情,查询一个不存在的ID,每次都会访问DB,如果有人恶意破坏,很可能直接对DB造成过大的压力。

解决方案

1.增加二级缓存。查询时,如果key不存在,且DB中无数据,对这个不存的key设置一个标识key,进行缓存。以后再查询key时,先查询标识缓存,如果标识缓存存在则返回一个false或者NULL值的默认值,APP做相应处理。这个标识key的失效时间不能太长。一般5分钟左右。

2.查询时,key不存在且DB中无数据,直接将KEY和NULL缓存进去,并且返回App,当然这个缓存过期时间会很短。

3.采用布隆过滤器,将所有的DB数据缓哈希到一个足够大的bitMap中,一个一定不存在的数据会被这个bitMap拦截掉,从而避免了对底层存储系统的查询压力。

缓存雪崩:可能是因为数据未加载到缓存中,或者同一时间缓存大面积的失效,从而导致所有的请求都去查询数据库,导致数据库CPU和内存负载过高,甚至宕机。

解决方案:

1.加锁计数(即限制并发数量)或者起一定数量的队列来避免缓存失效时大量的请求并发到数据库。但这种方式会降低吞吐量。

2.分析用户行为,然后均匀分布缓存失效时间。或者在失效时间的基础上再加上1~5分钟的随机数。

3.如果是某台缓存服务器宕机,可以考虑做主从配置。

热点KEY:缓存中的某些key对应的value存储在集群中的一台机器上,使得所有的流量涌向同一台机器,称为系统瓶颈,该问题的挑战在于不能用增加机器容量来解决。

解决方案:

1.客户端热点key缓存:将热点key对应的value缓存到客户端本地,并且设置一个失效时间。对于每次请求,先检查key是否存在于本地缓存中,如果有则直接返回,不去访问分布式缓存的机器。当然失效时间不能太长。

2.将热点key分散为多个子KEY,然后存储到缓存集群不同的机器上,这些子key的value和key的value是一样的。当通过热点key去查询数据是,通过某种hash算法随机去选择一个子key,然后去访问缓存机器,将压力分散到不同的机器上。

3.“永不过期”:

    这里的"永不过期"包含两层意思:

     (1)从redis看,不设置过期时间,这就保证了不会出现热点key过期问题,也就是“物理”的不过期。

     (2)从功能上看,把过期时间设置在key对应的value里,如果发现要过期了,通过一个后台异步线程进行缓存的构建,这个过期时间,也就是“逻辑”上的不过期。从实战看,这种方法对于性能非常的友好,唯一不足的就是构建缓存的时候,其余线程可能访问的是老数据,但是对于一般互联网功能来说这个也是可以接受的。

    String get(final String key) {  
            V v = redis.get(key);  
            String value = v.getValue();  
            long timeout = v.getTimeout();  
            if (v.timeout <= System.currentTimeMillis()) {  
                // 异步更新后台异常执行  
                threadPool.execute(new Runnable() {  
                    public void run() {  
                        String keyMutex = "mutex:" + key;  
                        if (redis.setnx(keyMutex, "1")) {  
                            // 3 min timeout to avoid mutex holder crash  
                            redis.expire(keyMutex, 3 * 60);  
                            String dbValue = db.get(key);  
                            redis.set(key, dbValue);  
                            redis.delete(keyMutex);  
                        }  
                    }  
                });  
            }  
            return value;  
        }  

猜你喜欢

转载自blog.csdn.net/zxp0727/article/details/87864449