面试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 + "不存在");
        }
    }
}
相关推荐
只因在人海中多看了你一眼1 小时前
分布式缓存 + 数据存储 + 消息队列知识体系
分布式·缓存
Dlwyz2 小时前
redis-击穿、穿透、雪崩
数据库·redis·缓存
工业甲酰苯胺4 小时前
Redis性能优化的18招
数据库·redis·性能优化
Oak Zhang7 小时前
sharding-jdbc自定义分片算法,表对应关系存储在mysql中,缓存到redis或者本地
redis·mysql·缓存
门牙咬脆骨8 小时前
【Redis】redis缓存击穿,缓存雪崩,缓存穿透
数据库·redis·缓存
门牙咬脆骨8 小时前
【Redis】GEO数据结构
数据库·redis·缓存
周三有雨9 小时前
【面试题系列Vue07】Vuex是什么?使用Vuex的好处有哪些?
前端·vue.js·面试·typescript
墨鸦_Cormorant9 小时前
使用docker快速部署Nginx、Redis、MySQL、Tomcat以及制作镜像
redis·nginx·docker
爱米的前端小笔记10 小时前
前端八股自学笔记分享—页面布局(二)
前端·笔记·学习·面试·求职招聘
好学近乎知o10 小时前
解决sql字符串
面试