缓存穿透
缓存穿透就是大量请求的key根本不存在于缓存中,导致请求直接到了数据库中,根本没有经过缓存这一层
我们经常会把一部分数据放在Redis中缓存,比如文章详情。
这样有查询请求进来,我们可以根据文章Id直接去缓存中取数据,而不用读取数据库,这是提升性能最简单,最普遍,也是最有效的做法。
一般的查询请求流程是这样的:先查缓存(有缓存的话直接返回)-> 如果缓存中没有,再去数据库查询(把数据库取出来的数据放入缓存)-> 返回数据。
问题:如果现在有大量的请求进来,而且都在请求一个不存在的文章id,那么将会发生什么
因为文章id都不存在,那么肯定没有对应的缓存信息。没有缓存。那么大量的请求都堆积到数据库,数据库的压力倍增。
解决方式:
最基本的就是首先做好参数校验,一些不合法的参数请求直接抛出异常信息返回给客户端,比如查询的数据库id不能小于0,传入的邮箱格式不对的时候直接返回错误消息给客户端等
- 缓存无效key
如果缓存和数据库都查不到这个key的数据就写到redis中并设置过期时间。
- 最好的方法是设置一个布隆过滤器,通过可以方便的判断一个给你说那个数据是否存在海量数据中。
需要判断key是否合法
具体做法:把所有可能存在的请求的值都放在布隆过滤器中,当用户请求过来,先判断用户发出来的请求的值是否存在于布隆过滤器中。不存在返回请求参数错误信息发送给给客户端,存在的话判断是否在redis缓存中,不在继续在数据库中查找。
布隆过滤器实现原理:
哈希函数
将任意大小的数据转换成特定大小的数据的函数,转换后的数据称为哈希值或哈希编码。示意图如下所示:
可以明显的看到,原始数据经过哈希函数的映射后成为了一个个的哈希编码,数据得到压缩。哈希函数是实现哈希表和布隆过滤器的基础。
数据结构
布隆过滤器的核心实现是一个超大的位数组和几个哈希函数
具体操作的流程如下:
假设集合里面有3个元素{x, y, z},哈希函数的个数为3。将位数组进行初始化,将里面每个位都设置为0。
- 设置:对于集合{x, y, z}里面的每一个元素,将元素依次通过3个哈希函数进行映射,每次映射都会产生一个哈希值,这个值对应位数组上面的一个点,然后将位数组对应的位置标记为1(这样位置2、4、5、6、12、14、17均为1)。
- 查询:判断W元素是否存在集合中的时候,同样的方法将W通过哈希映射到位数组上的3个点(位置:5、14、16)。如果3个点的其中有一个点不为1,则可以判断该元素一定不存在集合中。反之,如果3个点都为1,则该元素可能存在集合中
注意:此处不能判断该元素是否一定存在集合中,可能存在一定的误判率。
假设某个元素通过映射对应下标为4,5,6 这3个点。虽然这3个点都为1,但是很明显这3个点是不同元素经过哈希得到的位置,因此这种情况说明元素虽然不在集合中,也可能对应的都是1,由此推断出误判率存在的可能性。
总结:查询函数
将要查询的元素给k个哈希函数,得到对应于位数组上的k个位置,如果k个位置有一个为0,则肯定不在集合中,如果k个位置全部为1,则可能在集合中
参考博客:
https://blog.csdn.net/ZhangHuan0126/article/details/109362634