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

条件

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

解决方法

使用布隆过滤器

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

原理总结

1.一个很长的二进制数组 (位数组,就是这个数组里只有0和1)

2.若干个哈希函数

3.空间效率和查询效率高

4.不存在漏报(False Negative),即某个元素在某个集合中,肯定能报出来。

5.可能存在误报(False Positive),即某个元素不在某个集合中,可能也被爆出来。

5.删除困难

代码实现布隆过滤器

java 复制代码
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依赖

XML 复制代码
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>27.0.1-jre</version>
</dependency>

代码实现

java 复制代码
public static void main(String[] args) {
    // 1.创建符合条件的布隆过滤器
    // 预期数据量10000,错误率0.0001
    BloomFilter<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 + "不存在");
        }
    }
}
相关推荐
Redstone Monstrosity30 分钟前
字节二面
前端·面试
码爸1 小时前
flink 批量压缩redis集群 sink
大数据·redis·flink
UestcXiye2 小时前
面试算法题精讲:求数组两组数差值和的最大值
面试·数据结构与算法·前后缀分解
严格格2 小时前
三范式,面试重点
数据库·面试·职场和发展
微刻时光2 小时前
Redis集群知识及实战
数据库·redis·笔记·学习·程序人生·缓存
丁总学Java2 小时前
如何使用 maxwell 同步到 redis?
数据库·redis·缓存
蘑菇蘑菇不会开花~3 小时前
分布式Redis(14)哈希槽
redis·分布式·哈希算法
爱吃南瓜的北瓜3 小时前
Redis的Key的过期策略是怎样实现的?
数据库·redis·bootstrap
WG_173 小时前
C++多态
开发语言·c++·面试
小菜yh3 小时前
关于Redis
java·数据库·spring boot·redis·spring·缓存