缓存穿透指查询不存在的数据导致请求直达存储层,解决方案包括缓存空对象和布隆过滤器:缓存空对象适用于空数据较少场景,布隆过滤器适合空数据较多场景,可结合使用。
缓存穿透是指查询一个根本不存在的数据,缓存层和存储层都不会命中,导致每次请求都直接打到存储层。这会给存储层带来巨大的压力,甚至可能导致服务崩溃。简单来说,就是“查无此项”带来的麻烦。
解决缓存穿透,核心思路是避免请求直接打到存储层。
解决方案:
缓存空对象: 当存储层返回空结果时,仍然将这个空结果缓存起来,但设置一个较短的过期时间。下次再查询相同Key时,缓存层会直接返回空结果,避免继续访问存储层。这个方法简单直接,但要注意过期时间的设置,过长可能导致数据不一致,过短则效果不佳。
布隆过滤器: 在缓存层前面设置一个布隆过滤器,将所有可能存在的Key预先加载到布隆过滤器中。当收到一个查询请求时,先判断Key是否存在于布隆过滤器中。如果不存在,则直接返回,避免访问缓存层和存储层。布隆过滤器是一种概率型数据结构,存在一定的误判率(False Positive),但可以有效地过滤掉大部分不存在的Key。
接口校验: 在接口层面进行校验,例如对用户ID进行格式校验,过滤掉明显非法的请求。这个方法可以防止恶意攻击,但需要根据具体的业务场景进行设计。
选择哪种方案取决于具体的业务场景。
一般来说,如果对误判率要求不高,且数据不存在的情况比较多,布隆过滤器是更好的选择。如果对误判率要求很高,或者数据不存在的情况比较少,缓存空对象是更好的选择。当然,也可以将两种方案结合使用,例如先使用布隆过滤器过滤掉大部分不存在的Key,再使用缓存空对象处理少量误判的Key。
布隆过滤器的关键在于选择合适的哈希函数个数 k 和位数组大小 m。这两个参数会影响布隆过滤器的误判率。
一般来说,可以根据以下公式估算合适的 m 和 k:
其中,n 是预计要存储的Key的数量。
例如,假设要存储100万个Key,希望误判率低于1%,那么可以计算出 m ≈ 9585058,k ≈ 7。
在实际应用中,可以使用现成的布隆过滤器库,例如 Google Guava 的
BloomFilter
import com.google.common.hash.BloomFilter; import com.google.common.hash.Funnels; public class BloomFilterExample { public static void main(String[] args) { int expectedInsertions = 1000000; double fpp = 0.01; // 期望的误判率 BloomFilter<Integer> bloomFilter = BloomFilter.create( Funnels.integerFunnel(), expectedInsertions, fpp); // 添加元素 for (int i = 0; i < expectedInsertions; i++) { bloomFilter.put(i); } // 测试元素是否存在 System.out.println(bloomFilter.mightContain(1)); // true System.out.println(bloomFilter.mightContain(1000000)); // false,但也可能误判为true } }
缓存空对象的过期时间需要根据具体的业务场景进行权衡。
一般来说,可以根据以下原则设置过期时间:
一个常用的方法是使用动态过期时间。例如,可以根据存储层的响应时间来动态调整过期时间。如果存储层的响应时间比较快,那么可以设置较短的过期时间;如果存储层的响应时间比较慢,那么可以设置较长的过期时间。
还有一种比较少见的方案是存储层拦截。在存储层(例如数据库)中,可以设置一个拦截器,当收到一个查询请求时,先判断Key是否存在。如果不存在,则直接返回空结果,避免执行实际的查询操作。
这种方案的优点是可以完全避免缓存穿透,但缺点是会增加存储层的负担,并且需要修改存储层的代码。因此,除非对性能要求非常高,否则不建议使用这种方案。
另外,一些云服务提供商也提供了内置的缓存穿透防护功能,例如阿里云的CDN和腾讯云的DDoS防护。这些功能通常基于布隆过滤器或其他类似的技术,可以有效地防止缓存穿透攻击。
以上就是什么是缓存穿透?怎么解决?的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号