- 缓存击穿:key对应的数据存在,但在redis中过期,此时若有大量并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。
- 缓存穿透:key对应的数据在数据源并不存在,每次针对此key的请求从缓存获取不到,请求都会到数据源,从而可能压垮数据源。比如用一个不存在的用户id获取用户信息,不论缓存还是数据库都没有,若黑客利用此漏洞进行攻击可能压垮数据库。
- 缓存雪崩:当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,也会给后端系统(比如DB)带来很大压力。
缓存击穿在单节点的情况下对应的解决方案就是多线程锁:比如说现在一个线程抢到了锁,然后设置锁的过期时间为30s,然后另外一个线程也拿到了锁,开始处理业务,同时开启另外一个线程监管锁的过期时间,当这个在处理业务时,发现锁的过期时间剩余10s了,然后监管线程又把时间重新设置为30s,这样业务处理不完不释放锁,这样第一个线程挂了,30s一到释放锁,第二个线程处理完业务,会主动释放锁,这样就完美解决了缓存击穿的问题
缓存穿透最常用的方法就是布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力,另外也有一个更为简单粗暴的方法,如果一个查询返回的数据为空,我们仍然把这个空结果进行缓存,但是过期时间很短,最长不超过5分钟
缓存雪崩业内常用的方案是加锁或队列的方式来保证不会有大量的线程对数据库进行一次性读写操作,从而避免失效时大量的并发请求落到底层存储系统上,还有一个简单的方式就是,对key设置过期时间的时候增加一个随机数,把过期时间分散开,避免集体失效的问题