面试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 + "不存在");
        }
    }
}
相关推荐
Eren7Y琳14 小时前
开箱即用构建应用环境:openEuler易获得性深度验证
redis·设计模式·架构
踏浪无痕14 小时前
从单体PHP到微服务:一个五年老项目的血泪重构史
后端·面试·架构
第二只羽毛14 小时前
C++高性能内存池
开发语言·c++·缓存·性能优化
萝卜青今天也要开心15 小时前
2025年下半年系统架构设计师考后分享
java·数据库·redis·笔记·学习·系统架构
阿伟*rui15 小时前
互联网大厂Java面试:音视频场景技术攻防与系统设计深度解析
java·redis·websocket·面试·音视频·高并发·后端架构
Java天梯之路15 小时前
Spring AOP:面向切面编程的优雅解耦之道
java·spring·面试
DemonAvenger15 小时前
Redis集群架构详解:从单机到分布式的扩展之路
数据库·redis·性能优化
北慕阳15 小时前
(1)八股文 算法
面试·职场和发展
卿雪15 小时前
Redis 数据持久化:RDB和 AOF 有什么区别?
java·数据库·redis·python·mysql·缓存·golang
闲人编程15 小时前
微服务API网关设计模式
python·缓存·微服务·设计模式·系统安全·api·codecapsule