什么是缓存穿透、缓存雪崩 及 解决缓存穿透、雪崩解决方案实现
  7jPfnBIFtnum 2024年08月02日 30 0

1、 缓存穿透问题的解决思路

缓存穿透 :

缓存穿透 是 指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库。


常见的解决方案有两种:

  1. 缓存空对象

优点:

  • 实现简单,维护方便

缺点:

  • 额外的内存消耗
  • 可能造成短期的不一致
  1. 布隆过滤

优点:

  • 内存占用较少,没有多余key

缺点:

  • 实现复杂
  • 存在误判可能

什么是缓存穿透、缓存雪崩 及 解决缓存穿透、雪崩解决方案实现


缓存空对象思路分析:

当我们客户端访问不存在的数据时,先请求redis,但是此时redis中没有数据,此时会访问到数据库,但是数据库中也没有数据,这个数据穿透了缓存,直击数据库,我们都知道数据库能够承载的并发不如redis这么高,如果大量的请求同时过来访问这种不存在的数据,这些请求就都会访问到数据库。

简单的解决方案就是哪怕这个数据在数据库中也不存在,我们也把这个数据存入到redis中去,这样,下次用户过来访问这个不存在的数据,那么在redis中也能找到这个数据就不会进入到缓存了

布隆过滤:

布隆过滤器其实采用的是哈希思想来解决这个问题,通过一个庞大的二进制数组,走哈希思想去判断当前这个要查询的这个数据是否存在,如果布隆过滤器判断存在,则放行,这个请求会去访问redis,哪怕此时redis中的数据过期了,但是数据库中一定存在这个数据,在数据库中查询出来这个数据后,再将其放入到redis中。

假设布隆过滤器判断这个数据不存在,则直接返回

这种方式优点在于节约内存空间,存在误判,误判原因在于:布隆过滤器走的是哈希思想,只要哈希思想,就可能存在哈希冲突

什么是缓存穿透、缓存雪崩 及 解决缓存穿透、雪崩解决方案实现


① 编码解决商品查询的缓存穿透问题:

核心思路如下:

  • 在原来的逻辑中:

我们如果发现这个数据在mysql中不存在,直接就返回404了,这样是会存在缓存穿透问题

  • 现在的逻辑中:

如果这个数据不存在,我们不会返回404 ,还是会把这个数据写入到Redis中,并且将value设置为空当再次发起查询时,我们如果发现命中之后,判断value是否是null,如果是null,则是之前写入的数据,证明是缓存穿透数据,如果不是,则直接返回数据。

什么是缓存穿透、缓存雪崩 及 解决缓存穿透、雪崩解决方案实现


代码:

修改 ShopServiceImpl 中 queryShopById 方法 中的 不存在逻辑

    /**
     *  查询商铺
     * @param id
     * @return
     */
    @Override
    public Result queryShopById(Long id) {

        // 1. 从 Redis 中查询商铺缓存
        String shopJson = stringRedisTemplate.opsForValue().get(CACHE_SHOP_KEY + id);

        // 2. 判断是否存在
        // 3. 存在 , 直接返回
        if(StrUtil.isNotBlank(shopJson)){
            Shop shop=JSONUtil.toBean(shopJson, Shop.class);
            return Result.ok(shop);
        }

        //判断命中空值 返回 404
        if(shopJson != null) {
            // 返回一个错误信息
            return Result.fail("商铺不存在");
        }

        // 4. 不存在 ,根据 id 去数据库查询
        Shop shop = getById(id);
        // 5. 不存在 , 返回 404
        if(shop==null){
            stringRedisTemplate.opsForValue().set(CACHE_SHOP_KEY + id, "",CACHE_NULL_TTL,TimeUnit.MINUTES);
            return Result.fail("商铺不存在");
        }

        // 6. 存在 , 写入 Redis
        stringRedisTemplate.opsForValue().set(CACHE_SHOP_KEY + id, JSONUtil.toJsonStr(shop),CACHE_SHOP_TTL, TimeUnit.MINUTES);

        return Result.ok(shop);
    }

什么是缓存穿透、缓存雪崩 及 解决缓存穿透、雪崩解决方案实现


② 总结:

  1. 缓存穿透产生的原因是什么?

用户请求的数据在缓存中和数据库中都不存在不断发起这样的请求,给数据库带来巨大压力

  1. 缓存穿透的解决方案有哪些
  • 缓存null值
  • 布隆过滤
  • 增强id的复杂度,避免被猜测id规律
  • 做好数据的基础格式校验
  • 加强用户权限校验
  • 做好热点参数的限流

2、 缓存雪崩问题及解决思路

缓存雪崩:

缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机,导致大量请求到达数据库,带来巨大压力。

解决方案:

  1. 给不同的Key的TTL添加随机值
  2. 利用Redis集群提高服务的可用性
  3. 给缓存业务添加降级限流策略
  4. 给业务添加多级缓存

什么是缓存穿透、缓存雪崩 及 解决缓存穿透、雪崩解决方案实现


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2024年08月02日 0

暂无评论

推荐阅读
  7jPfnBIFtnum   2024年06月14日   208   0   0 存储redis内存
  7jPfnBIFtnum   2024年06月14日   112   0   0 redis缓存数据库
7jPfnBIFtnum