这个是大厂面试热点!只要问到Redis,没有不问这个的。
先读cache,如果数据命中则返回;如果数据未命中则读db;将db中读取出来的数据入缓存。
private Map cache = new ConcrrentHashMap();
Object getFromCache(String key){
Object value = cache.get(key);
if(value==null){
value = getByKey(key);
cache.put(key,value);
}
return value;
}
访问一个不存在的key,缓存不起作用,请求会穿透到DB,流量大时DB会挂掉。
解决方案 (1)采用布隆过滤器,使用一个足够大的bitmap,用于存储可能访问的key,不存在的key直接被过滤;(注意:说完布隆过滤器,就要被问到布隆过滤器的原理了,准备下!) (2)拦截器,接⼝层增加校验,如给id做校验,id<=0的直接拦截。 (3)从cache和db都取不到,可以将key-value写为key-null,设置较短过期时间,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击。
一个存在的key,在缓存过期的一刻,同时有大量的请求,这些请求都会击穿到DB,造成瞬时DB请求量大、压力骤增。
解决方案 (1)设置热点数据永远不过期。 (2)加互斥锁。
大量的key设置了相同的过期时间,导致在缓存在同一时刻全部失效,造成瞬时DB请求量大、压力骤增,引起雪崩。
解决方案 主要说前三个就可以啦! (1)缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。 (2)如果缓存数据库是分布式部署,将热点数据均匀分布在不同的缓存数据库中。 (3)设置热点数据永远不过期。 (4)使用互斥锁,但是该方案吞吐量明显下降了。 (5)双缓存。我们有两个缓存,缓存A和缓存B。缓存A的失效时间为20分钟,缓存B不设失效时间。自己做缓存预热操作。然后细分以下几个小点:
掌握了吧!必须加分了!