Redis缓存击穿和缓存雪崩、缓存穿透以及对应的解决方案

目录

缓存击穿

缓存击穿的解决方案

缓存雪崩

缓存雪崩的解决方案

缓存穿透

布隆过滤器


缓存击穿

一般我们会对缓存的key设置过期时间,在高并发下,如果在某一时刻这个key刚好过期,此时持续的大并发请求都会穿破缓存,直接命中DB,就像在一个屏障上凿开了一个洞。

缓存击穿的解决方案

1)  通过分布式锁或者队列,使得同一个key只允许一个线程到数据库查询
2)定时预先更新缓存,避免发生缓存失效的情形

不过一般情况下单个缓存的击穿很难对数据库造成压垮性的压力

缓存雪崩

缓存雪崩是指缓存中的大量的key在同一时间失效,导致所有的请求都命中DB,使得其无法负载。简单来说就是大量key同时发生缓存击穿的情形

缓存击穿针对的是某一个设置了过期时间的缓存,缓存雪崩针对的是很多设置了过期时间的缓存

缓存雪崩的解决方案

1)  通过分布式锁或者队列,使得同一个key只允许一个线程到数据库查询
2)定时预先更新缓存,避免同时发生缓存失效的情形
3)通过加随机数,使得不同的key在不同的时间过期
4)设置缓存永不过期

缓存穿透

缓存穿透,是指查询一个数据库一定不存在的数据。通常redis没有缓存的时候,我们就会去访问数据库获取数据,此时如果数据库也不存在数据,那么每次对该key的请求都会命中数据库,在高并发情形下,就会导致数据库压力过大从而崩溃。

如果每次请求的数据都是同一个key,那么可以通过缓存空数据或者特殊字符串,比如&&来避免缓存穿透(需要对这个缓存设置一个过期时间,否则数据库新增了这一数据也无法获取到对应值)

但是如果每次请求的key都不一样,那么我们就需要其他的方法来判断一个key是否存在于数据库中,不能直接通过查询数据库的方式来判断
因为缓存的往往是大量的数据,直接存储所有的数据显然费空间又费时间,为了节省存储空间,可以采用BitMap(位图)的方式来标记这个key是否出现过

对于每一个元素,我们通过哈希函数对key进行运算,得到一个下标,将其对应的位图上的值改为1,就表示该元素在这个集合存在。因为哈希碰撞的存在,我们可以采用
1.扩大数组的长度或者说位图容量 (空间消耗加大)
2.引入很多个哈希函数 (耗时)


来减小哈希碰撞的概率

实际使用中,我们既要节省空间,又要很高的计算效率,就必须在位图容量和函数个数之间找到一个最优解,布隆过滤器就帮助我们解决了这个问题

布隆过滤器

1970年由Burton Howard Bloom提出,其目的就是为了快速判断一个集合里是否存在某一个元素

bloom过滤器实际是由一个长位图和k个不同的哈希函数组成的

其过程主要分为三步:

1.创建一个二进制数组,所有的值都初始化为0
2.将集合里的每一个元素都通过k个hash函数运算其在位图的下标

3.将对应的下标的值改为1

判断某个元素是否存在于集合的时候,我们只需要判断元素通过k个hash函数计算出来的下标在位图上是否都为1就可以了,如果全部为1,则表示该元素很可能存在;否则该元素就一定不存在(这是因为hash碰撞无法避免,会导致有一定的误判率,会将不存在的元素误判为存在)

这种把本来不存在布隆过滤器中的元素误判为存在的情况,我们把它叫做假阳性(False Positive Probability,FPP)。

        Funnel<String> funnel = new Funnel<String>() {
            @Override
            public void funnel(String from, PrimitiveSink into) {
                into.putString(from, Charsets.UTF_8);
            }
        };
        //  创建符合条件的布隆过滤器 误判率为0.1%,集合元素最大预计为一万
        BloomFilter<String> filter = BloomFilter.create(funnel, 10000, 0.001);
        filter.put("chenpp");
        System.out.println(filter.mightContain("chenpp"));
        System.out.println(filter.mightContain("chenpp11"));

如果在缓存中使用布隆过滤器,其流程图如下:

首先每次在数据库新增数据的时候,都需要把数据同步到BloomFilter中

在查询数据的时候,先在布隆过滤器查询,如果返回说没有,那数据库中也肯定没有,就不需要查了,只有返回为存在的数据才需要查询缓存和DB
 

发布了47 篇原创文章 · 获赞 12 · 访问量 5073

猜你喜欢

转载自blog.csdn.net/qq_35448165/article/details/103269269