缓存击穿、雪崩、穿透

8 篇文章 0 订阅

缓存击穿

    /**
     * 缓存击穿:高并发时,当一个key非常热点(热销品),在不停的扛着大并发,当这个key在失效的瞬间,持续的大并发就击穿缓存,直接请求数据库后再缓存数据,导致性能下降
     * 解决方案:永不过期 或 加锁排队 或 两者都有
     *
     * @param key 键
     * @return {@link String}
     */
    public String cacheBreakdown(String key) {
        String value = stringRedisTemplate.opsForValue().get(key);
        if (StringUtils.isNotBlank(value)) {
            return value;
        }
        synchronized (this) {
            value = stringRedisTemplate.opsForValue().get(key);
            if (StringUtils.isNotBlank(value)) {
                return value;
            }
            // 从数据库中获取数据
            value = selectDb(key);
            stringRedisTemplate.opsForValue().set(key, value, Duration.ofHours(1L));
        }
        return value;
    }

缓存雪崩

    /**
     * 缓存雪崩:缓存集中过期,或者缓存服务器宕机,导致大量请求访问数据库,造成数据库瞬间压力过大,宕机
     * 解决方案:加锁排队 和 随机失效时间 和 redis集群部署
     *
     * @param key 钥匙
     * @return {@link String}
     */
    public String cacheAvalanche(String key) {
        String value = stringRedisTemplate.opsForValue().get(key);
        if (StringUtils.isNotBlank(value)) {
            return value;
        }
        synchronized (this) {
            value = stringRedisTemplate.opsForValue().get(key);
            if (StringUtils.isNotBlank(value)) {
                return value;
            }
            // 从数据库中获取数据
            value = selectDb(key);
            // 设置随机失效时间
            long hour = ThreadLocalRandom.current().nextLong(1L, 31L);
            stringRedisTemplate.opsForValue().set(key, value, Duration.ofHours(hour));
        }
        return value;
    }

缓存穿透

    /**
     * 缓存穿透:数据库不存在且缓存中也不存在,导致每次请求都会查询数据库,这时的请求很可能是攻击者,伪造不存在的 key ,导致数据库压力过大或宕机
     * 解决方案:参数校验(如ID≤0的key值请求一律返回空) 和 缓存空对象 和 使用 bloom 过滤器
     *
     * @param key 钥匙
     * @return {@link String}
     */
    public String cachePenetration(String key) {
        // RedissonClient redissonClient = Redisson.create();
        RBloomFilter<Long> bloomFilter = redissonClient.getBloomFilter("bloom:filter:data");
        if (!bloomFilter.contains(Long.parseLong(key))) {
            return null;
        }
        String value = stringRedisTemplate.opsForValue().get(key);
        if (StringUtils.isNotBlank(value)) {
            return value;
        }
        synchronized (this) {
            value = stringRedisTemplate.opsForValue().get(key);
            if (StringUtils.isNotBlank(value)) {
                return value;
            }
            // 从数据库中获取数据
            value = selectDb(key);
            if (StringUtils.isBlank(value)) {
                // 缓存空对象
                stringRedisTemplate.opsForValue().set(key, "{}", Duration.ofMinutes(10L));
                return value;
            }
            // 设置随机失效时间
            long hour = ThreadLocalRandom.current().nextLong(1L, 31L);
            stringRedisTemplate.opsForValue().set(key, value, Duration.ofHours(hour));
        }
        return value;
    }

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值