缓存击穿
在读多写少的高并发应用场景,通常会通过使用缓存(memcached,redis,tair等)来提升性能,我们大致所做的就是请求来了先查询缓存,缓存没有对应的数据再查询db,之后set到缓存中同时返回给前台,有一种情况,恶意使用不存在的key去查询,这样会导致必然不走缓存,直接将请求打到db,这种带有攻击性的访问需要被拦截过滤掉
处理方法
1.使用bloomfilter对其进行过滤,原理是将db的数据放入布隆过滤器,请求过来查询缓存之前先查询是否存在于布隆过滤器,存在则进行后续操作,不存在则直接返回
2.在查询缓存未果,查询db的也返回空的时候,将key和空值设置缓存,缓存时间设置的小一些比如5分钟,这样可以暴利的拦截缓存击穿
缓存失效
我们设置的缓存具有失效时间的情况下,如果该失效时间都相同,则在同一时间段会同时失效,这时候如果处在并发量大的时候,例如外卖行业在中午进行订餐的时候,或者电商进行大促的时候,则会造成大量请求直接打到db
处理方法
在设置缓存的时候可以在固定时间上增加一个随机数,确保缓存不会同一时间失效
热点key失效
如果某一个热点key失效,则会造成大量请求去访问,发现没有缓存,则会同时请求db查询
处理方法
可使用分布式锁对其进行控制,原理是多个线程访问,可采用redis的setnx进行控制,在第一个线程去查询db的时候确保其他线程处于等待阶段,当第一个线程查询完并且设置缓存,其他线程则直接读取缓存数据进行返回,简单的demo
public String get(key) {
String value = redis.get(key);
if (value == null) {
if (redis.setnx(key_mutex, 1, 3 * 60) == 1) { //缓存不存在(设置成功)则会返回1,该线程拿到锁
value = db.get(key);
redis.set(key, value, expire_secs);
redis.del(key_mutex);
} else {
sleep(50);
get(key);
}
} else {
return value;
}
}