概念及问题:
1、缓存穿透:key在redis缓存不存在,db也不存在,因此必然会到db中load数据,如果有恶意攻击,获取该不存在的key,且并发量非常大时,就会导致db负载高,有可能压垮数据库。
2、缓存击穿:key存在,但是在redis中过期,这时会从db中load数据,此时如果有大量并发请求过来,也会导致db被压垮。
3、缓存雪崩:redis重启或者大量缓存集中失效,这时会从db中大量load数据,也会给db带来非常大的压力。
解决办法:
1、缓存穿透:问题本质是key不存在,这个可以通过一个布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免对底层存储系统的查询压力;还有另外一种方法,如果查询返回的数据为空,还是把这个缓存到redis中,但是过期时间设置短一点,一般不超过5分钟。
2、缓存击穿:这个是因为过期,肯定是要load数据,但是尽量在缓存层面拦住,比较好的方式时,让一个请求去db load数据,其他先等着或者循环一会再到redis取。方式是设置一个互斥锁mutex,具体实现是redis查不到数据,做个setnx(set if not exist),如果set成功,去db load数据,如果set失败,做个休眠50ms,再到redis查询。
3、缓存雪崩:主要是因为缓存集中查不到,这个时候,从db捞取数据是不可避免的,这个时候就是通过加锁或者队列方式来拦住,对于缓存集中失效,一般可以通过设置key的失效时间做一定分散,避免集中。
这几个问题,解决方法不一定都要采用,不同的系统的需求和遇到的问题是不一样的,假如并发都不大,或者前端请求控制也比较强,那么后面这些也就不一定要做了。