缓存雪崩
-
当缓存服务器端重启或者大量缓存集中在某个时间段失效时,所有的请求会直接请求到后端系统+主数据库中去,从而导致系统的崩溃
解决方案- 在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。
- 启用限流策略
- 做二级缓存,A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期。
- 不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。
缓存穿透
-
大多数缓存系统,都会按照Key查询Value,如果不存在对应得Key,就会去后端系统+主数据库中去查找,然后一些恶意的请求就会查询不存在的Key,并且请求量很大,这样就对服务器端造成很大的压力,有可能会造成缓存穿透。
解决方案 -
对查询结果为空的情况也进行缓存,缓存时间设置短一点。
-
把所有的可能存在的key放到一个Bitmap中,查询时通过bitmap过滤。
-
由于请求参数是不合法的(每次都请求不存在的参数),于是我们可以使用布隆过滤器Bloomfilter提前进行拦截。
缓存击穿
-
一个存在的Key,在缓存过期的一刻,同时有大量的请求过来,这些请求都会击穿数据库,造成数据库请求量很大,压力剧增。
解决方案 -
使用互斥锁,在访问key之前,采用SETNX(set if not exists)来设置另一个短期key来锁住当前key的访问,访问结束再删除该短期key
-
就是在缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用缓存工具的某些带成功操作返回值的操作(Redis的SETNX)去set一个短期的mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法。
-
方法加锁 + 双重校验
-
后台定义一个job(定时任务)专门主动更新缓存数据.比如,一个缓存中的数据过期时间是30分钟,那么job每隔29分钟定时刷新数据(将从数据库中查到的数据更新到缓存中).