一、简介
本文的内容讲的是使用Redis做缓存的过程中,出现的缓存穿透及解决方案。
二、缓存穿透的原因
查询不存在的数据: 当有恶意用户或攻击者发送请求,试图查询一个不存在的数据时,缓存中不会命中该数据,每次请求都会直接访问数据库,而且对于相同的无效请求,缓存都无法起到过滤的作用,导致数据库负载增加。
高并发情况下的热点数据: 当某个热点数据在高并发情况下被大量请求访问时,缓存可能无法满足这么多请求的需求,导致大量请求直接访问数据库或其他数据源。这会使数据库或其他数据源出现压力过大的情况,并可能导致性能下降。
三、缓存穿透的解决方案
为了解决缓存穿透问题,可以采用以下几种方式:
1.布隆过滤器(Bloom Filter)
布隆过滤器的核心思想是使用多个独立的哈希函数对元素进行哈希计算,并将得到的哈希值映射到一个位图中的相应位置上。当对一个元素进行查询时,通过对该元素进行相同的哈希计算,并检查对应位图上的位置是否都为1,如果都为1,则表示该元素可能存在于集合中;如果某一位为0,则表示该元素一定不存在于集合中。
优点:空间效率高,因为位图基本上只需占用一个二进制位就可以表示元素的存在与否。另外,查询时只需要进行多次哈希计算和位图的判断操作,查询速度非常快。 缺点:当通过哈希函数计算出的索引位置被多个元素共享时,会出现误判现象,即某个元素可能并未被加入集合,但多个哈希函数都返回该位置为1,导致“误认为存在”。另外,无法删除已添加的元素,因为删除一个元素会影响到其他元素的判断。
2.缓存空对象(Cache Null Object)
缓存空对象是当查询一个不存在的键时,可以在缓存中存储一个表示空对象的值,用于表示该键对应的数据不存在。这样,在后续的请求中,当再次查询同一个键时,可以直接从缓存中获取到空对象的值,而不需要再次访问数据库。
具体的方式可以有以下三种:
1.存储空字符串或空值: 将一个空字符串或者null值作为表示空对象的值存储在缓存中。当缓存命中但值为空时,2即可判断该键对应的数据不存在。
2.使用特殊的标记值: 可以使用一些特殊的标记值作为表示空对象的值存储在缓存中,比如-1、0等。当缓存命中且值等于这些特殊的标记值时,可以判断该键对应的数据不存在。
3.使用自定义的空对象类或结构体: 定义一个表示空对象的类或结构体,然后将该对象存储在缓存中,表示该键对应的数据不存在。在查询时,当缓存命中且返回这个自定义的空对象时,可以判断数据不存在。
注意:缓存空对象只适用于那些很少发生变化、不会在短时间内再次被查询到的数据,对于频繁更新的数据,不适合使用缓存空对象的方式处理。在设置缓存空对象时,需要根据具体业务需求和数据特性来选择合适的方式,并确保缓存的一致性和正确性。
3.其他
增强查询值的复杂度,避免被猜测查询值规律
做好数据的基础格式校验
加强用户权限校验
做好热点参数的限流
四、总结
PS:
感谢您的阅读!如果您觉得本篇文章对您有所帮助,请给予博主一个赞喔~