缓存穿透
其实刚开始会觉得 这个场景没什么问题 查不到就查不到 不是很正常。 但是实际中可能担忧的一种情况就是, 攻击者会用大量的数据库中没有的key 进行请求轰炸, 这些存在的数据进行攻击,数据库瞬时压力增大,最终导致崩溃。
比较常见的解决方法是:
缓存空对象 : 意思说就是如果一个请求查不到 那我把key-null 存进redis。然后设置有效时间。
(这里注意一点 null 怎么正确的存取redis redis 存入null的方法)
但是这种方法问题很多,别的不说,人家用请求轰炸各种砸你 , 每一个不存在的请求你都把null存到redis, 那redis的内存会被严重消耗 全存了一大堆你的空数据的key。 这是其一, 还有万一你存redis的这段时间 那个查不到的数据 又进入的数据库 短期就会造成缓存不一致。
布隆过滤器
所以说说第二种 比较成熟的解决方法。
什么叫布隆过滤器呢, 它就是在客户端和redis 中间 再加一层。 就像spring中的拦截器一样, 在这就可以判断它是不是在数据库里面。如果不在 直接打回去。
神奇吧?
新手会好奇,布隆是怎么知道 数据库里面有没有数据的呢???
难道它每次都要取数据库做一下exists 查询?? 有没有数据???
肯定是不可能的
所谓的bf(简称)他是一个不完全精确的 set结构。 你可以用它的contains方法 判断对象是不是存在。
打个比方你可以把很多 1-100 的数字 扔进去, 这时候如果来个 101 它发现不认识 那没有 , 但是如果来个98 注意bf有个特点 不认识的肯定不认识 但是认识的它有时候会误判 比如98 可能不认识。 所以你适合用bf做那种排除性的操作。
至于bf的具体使用和原理 后面我再加一篇 单独记录一下。
其实对于缓存穿透 我们前面都是从 redis 和 数据库角度出发,还有一些方法也可以很有效的预防 比如:
- 增强id的复杂度 避免被猜测规律。
- 做好数据的基础格式校验。
- 加强用户权限校验
这些都是有用的。