Redis正常查询过程:
- 客户端发起查询数据的请求至查询系统
- 先在缓存中进行数据的查询
- 若存在则直接返回数据给客户端
- 若缓存中不存在查询的数据时,则继续在在数据库中进行查询
- 在数据库中进行查询
- 若存在要查询的数据,则将数据存入缓存中,并返回给客户端
- 若不存在,直接返回null给客户端
1.缓存穿透
1.1 产生原因
大量的高并发请求缓存和数据库中都没有的数据,导致每次请求都会请求到数据库,数据库压力瞬间骤增,从而压垮数据库(卡死或宕机)
实际场景:
- 数据原来存在,但是后来在缓存和数据库中被误删或清理掉了,但前端或前置的应用程序中还存在相关数据
- 恶意攻击,利用不存在的key或者恶意尝试导致产生大量不存在的数据业务请求
1.2 解决方案
1.2.1 业务层校验:
对于明显不符合的数据进行判断,直接返回错误请求
如:key本身规则校验、用户校验、登录状态、n秒内访问接口的次数限制等
1.2.2 不存在的数据设置短过期时间处理
对于数据库中不存在的数据,可以考虑先将这个空数据存入缓存,同时根据实际业务进行短过期时间的设定处理,过期时间要尽可能段短
缺点:
-
- 需要缓存层提供更多的内存来缓存这些对象,空对象多的时候会造成缓存内存的浪费,被恶意攻击时可能出现Redis内存占用不足的情况
- 短期内缓存与数据库中的数据可能存在不一致的情况
1.2.3 使用布隆过滤器
布隆过滤器是一中可以利用极小的内存判断大量的数据“一定不存在或者可能存在”的数据结构;
布隆过滤器BloomFilter是根据hashcode判断的,不同的字符串的hashcode可能相同,如果某个hashcode存在,它对应的字符串不一定是你想要的那个字符串
利用布隆过滤器,将查询的数据条件都哈希到一个足够大的布隆过滤器中,用户发送的请求过来时,先被布隆过滤器拦截,一定不存在的数据直接就被拦截返回了,从而可以避免缓存和数据库都不存在的数据进行查询访问,达到减轻此类情况下数据库压力的目的。
注:布隆过滤器是有一定的误差,所以一般需要配合一些接口流量的限制(规定用户在一段时间内访问的频率)、权限校验、黑名单等来解决缓存穿透的问题