面试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 = "[email protected]";
        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 + "不存在");
        }
    }
}
相关推荐
·云扬·9 分钟前
【PmHub面试篇】集成 Sentinel+OpenFeign实现网关流量控制与服务降级相关面试题解答
面试·职场和发展·sentinel
_一条咸鱼_33 分钟前
Android Runtime即时编译触发条件与阈值深度解析(38)
android·面试·android jetpack
让我上个超影吧35 分钟前
黑马点评【缓存】
java·redis·缓存
seventeennnnn1 小时前
Java大厂面试真题:谢飞机的技术挑战
java·spring boot·面试·aigc·技术挑战·电商场景·内容社区
AirMan1 小时前
你真的懂 MySQL 的一致性读和当前读的区别吗?
后端·面试
blammmp2 小时前
Redis: List类型
数据库·redis·缓存
why1512 小时前
6.12 操作系统面试题 进程管理
面试·操作系统
古夕2 小时前
Webpack 之 打包后的 bundle 文件内容解析
前端·面试·webpack
暴躁茹2 小时前
std::make_shared简化智能指针 `std::shared_ptr` 的创建过程,并提高性能(减少内存分配次数,提高缓存命中率)
缓存
古夕2 小时前
webpack 之 Loader 和 Plugin 接收参数对比
前端·面试·webpack