openshell 的个人博客 openshell 的个人博客

一天很长,但十年很短。

目录
缓存穿透、雪崩和击穿问题及其解决办法
/    

缓存穿透、雪崩和击穿问题及其解决办法

缓存穿透

描述

缓存和数据库中都没有数据,而用户不断发起这种系统中不存在的数据的请求,这种请求会增加数据库压力。

解决办法

  1. 将非法值放进redis中
    例如请求值为-1,最终在数据库也没有查到,那么就在redis中放入key:-1 value:null
    但这样会造成新的问题,如果遭遇大量攻击,redis的缓存的淘汰机制会淘汰掉本来需要用的值,redis内存也会有很大的负载压力。

  2. 布隆过滤器
    它能判断这个数据一定不在里面,但是不能判断这个数据一定在里面。

  • 布隆说不在,那么一定不在(不会)
  • 布隆说在,则可能不在(会误判)
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>21.0</version>
        </dependency>

public class RedisCacheDemo {
    static Jedis redis = new JedisPool("192.168.247.1", 6379).getResource();

    final static List<Integer> mysql = Arrays.asList(1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10);

    //创建布隆过滤器
    public static void createFilter(){
        //创建布隆过滤器
        filter = BloomFilter.create(
                Funnels.integerFunnel(), 1500, 0.01);
        //判断指定元素是否存在
        //将元素添加到布隆过滤器
        filter.put(1);
        filter.put(2);
    }

    static BloomFilter<Integer> filter;
    public static boolean idExists(int id){

       return filter.mightContain(id);
    }
    public static void main(String[] args) {

        Integer id = -1;

        String res = redis.get(id.toString());
        if (StringUtils.isNoneBlank(res)) {
            System.out.println(res);
            return;
        }

        // 使用布隆过滤器
        if (!idExists(id)){
            return;
        }
        //查询数据库
        if (mysql.contains(id)) {
            System.out.println("在数据库中id=" + id);
            redis.set(id.toString(), "XXX");
            redis.expire(id.toString(), 1);
            return;
        }

        System.out.println("不在数据库中 set redis");

    }
}

雪崩

描述

大量缓存同时失效,请求打在数据库上,数据库会在一瞬间挂掉。此时重启数据库,也会被新的流量打死。同一时间大面积缓存失效,就等于没有缓存了,数据库一个服务崩溃,若没有完备的熔断策略会导致一大片服务挂掉。

解决办法

批量往Redis中存数据时,随机设置key失效时间。

setRedis(Key,value,time + Math.random() * 10000);

缓存击穿

某一个热点数据失效,大量持续的并发穿破缓存,直接请求数据库。

解决办法:
热点数据永远不过期,或者加上互斥锁就行了。

参考文章:https://github.com/AobingJava/JavaFamily/blob/master/docs/redis/%E7%BC%93%E5%AD%98%E5%87%BB%E7%A9%BF%E3%80%81%E9%9B%AA%E5%B4%A9%E3%80%81%E7%A9%BF%E9%80%8F.md


标题:缓存穿透、雪崩和击穿问题及其解决办法
作者:openshell
地址:http://blog.caiqz.cn/articles/2020/06/09/1591717073600.html