缓存穿透是指缓存和数据库中都没有的数据,用户(黑客)不断发起请求,导致请求直接查询数据库,这种恶意行为攻击场景的会直接导致数据库挂掉,数据流程如下图所示:
处理这种情况相对比较简单点,这种情况是绕过redis或本地缓存直接到达数据库,可以采取以下方案:
-
在请求接口层可以做一些校验,比如用户签权、参数校验,不合法的请求直接return;
-
还可以针对有效id做认证或直接拦截,不符合的 id 直接过滤或采用统一key保存到redis,下次不合法的id请求时,直接到缓存中获取数据;
-
采用 redis 的高级接口 Bloom Filter,利用高效的数据结构和算法快速判断出你这个 Key 是否在数据库中存在,不存在你 return 就好了,存在你就去查 DB 刷新 KV 再 return。
-
缓存击穿
上面讲的穿透是针对大面积数据请求,那么击穿是针对一点(一个key)来来导致redis异常,但某个key是非常热点,请求非常频繁,处于集中式访问现象,当这个key失效(过期)时,大量的请求就会击穿了缓存,直接请求数据库,就像在屏障中凿开了一个洞。
不同场景下缓存击穿解决方案
-
数据基本不变:热点数据value基本不更新时,可以设置成永不过期
-
数据更新不频繁:缓存刷新流程耗时较少时,可采用redis、zookeeper等分布式中间件的分布式互斥锁或者本地互斥锁保证少量的请求能请求到数据库并重新更新缓存,其他的流程等锁释放后才可以访问新缓存
-
数据更新频繁:采用定时线程,在缓存过期前主动重新构建缓存或延长过期时间,保证所有的请求能一直访问缓存