当前位置:首页 > 编程笔记 > 正文
已解决

面试redis主题一“什么是缓存穿透”

来自网友在路上 153853提问 提问时间:2023-09-20 05:37:03阅读次数: 53

最佳答案 问答题库538位专家为你答疑解惑

条件

缓存穿透是因为查询redis时发现其中没有要查询的数据,大量请求DB导致DB压力过大崩溃。这种情况大部分是因为恶意攻击。

解决方法

使用布隆过滤器

它是一种基于概率的数据结构,主要用来判断某个元素是否在集合内,它具有运行速度快(时间效率),占用内存小的优点(空间效率),但是有一定的误识别率和删除困难的问题。它能够告诉你某个元素一定不在集合内可能在集合内

原理总结


1.一个很长的二进制数组 (位数组,就是这个数组里只有0和1)
2.若干个哈希函数
3.空间效率和查询效率高
4.不存在漏报(False Negative),即某个元素在某个集合中,肯定能报出来。
5.可能存在误报(False Positive),即某个元素不在某个集合中,可能也被爆出来。
5.删除困难

代码实现布隆过滤器

public class SimpleBloomFilter {private static final int DEFAULT_SIZE = 2 << 24;    // 布隆过滤器的比特长度private static final int[] seeds = new int[] {7, 11, 13, 31,37, 61};    // 这里要选取质数,能很好的降低错误率private BitSet bits = new BitSet(DEFAULT_SIZE);private SimpleHash[] func = new SimpleHash[seeds.length];public static void main(String[] args) {String value = "crankzcool@gmail.com";SimpleBloomFilter filter = new SimpleBloomFilter();System.out.println(filter.contains(value));filter.add(value);System.out.println(filter.contains(value));}public SimpleBloomFilter() {for (int i = 0; i < seeds.length; i++) {func[i] = new SimpleHash(DEFAULT_SIZE, seeds[i]);}}public void add(String value) {for (SimpleHash f: func) {bits.set(f.hash(value), true);}}public boolean contains(String value) {if (value == null) {return false;}boolean ret = true;for (SimpleHash f : func) {ret = ret && bits.get(f.hash(value));}return ret;}public static class SimpleHash {private int cap;private int seed;public SimpleHash(int cap, int seed) {this.cap = cap;this.seed = seed;}public int hash(String value) {int result = 0;int len = value.length();for (int i = 0; i < len; i++) {result = seed * result + value.charAt(i);}return (cap - 1) & result;}}

pom引入依赖实现布隆过滤器

pom依赖


<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>27.0.1-jre</version>
</dependency>

 代码实现

public static void main(String[] args) {// 1.创建符合条件的布隆过滤器// 预期数据量10000,错误率0.0001BloomFilter<CharSequence> bloomFilter =BloomFilter.create(Funnels.stringFunnel(Charset.forName("utf-8")),10000, 0.0001);// 2.将一部分数据添加进去for (int i = 0; i < 5000; i++) {bloomFilter.put("" + i);}System.out.println("数据写入完毕");// 3.测试结果for (int i = 0; i < 10000; i++) {if (bloomFilter.mightContain("" + i)) {System.out.println(i + "存在");} else {System.out.println(i + "不存在");}}
}


 

查看全文

99%的人还看了

猜你感兴趣

版权申明

本文"面试redis主题一“什么是缓存穿透”":http://eshow365.cn/6-9809-0.html 内容来自互联网,请自行判断内容的正确性。如有侵权请联系我们,立即删除!