redis缓存雪崩和缓存击穿

目录

 缓存雪崩

解决方案:

缓存击穿

​解决方案


 缓存雪崩

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

redis缓存雪崩和缓存击穿_第1张图片

解决方案:

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

缓存击穿

缓存击穿问题也叫热点Key问题,就是一个被高并发访问并且缓存重建业务较复杂key突然失效了,无数的请求访问会在瞬间给数据库带来巨大的冲击。

redis缓存雪崩和缓存击穿_第2张图片解决方案

        1.互斥锁

redis缓存雪崩和缓存击穿_第3张图片

        2.逻辑过期

redis缓存雪崩和缓存击穿_第4张图片

互斥锁和逻辑回归的优缺点 

互斥锁:

        优点:

没有额外的内存消耗
保证一致性
实现简单

         缺点:

线程需要等待,性能受影响
可能有死锁风险

逻辑回归:

        优点:

线程无需等待,性能较好

         缺点:

不保证一致性
有额外内存消耗
实现复杂

 使用互斥锁的形式解决缓存击穿

 public Shop queryWithMutex(Long id) throws InterruptedException {
        String key = CACHE_SHOP_KEY + id;
        //1.从redis中查询店铺缓存
        String jsonShop = stringRedisTemplate.opsForValue().get(key);
        //2.判断是否存在
        if (StrUtil.isNotBlank(jsonShop)) {
            //3.存在,直接返回
            return JSONUtil.toBean(jsonShop, Shop.class);
        }
        if ("".equals(jsonShop)) {
            return null;
        }
        //4.不存在,重建缓存
        //4.1  获取互斥锁
        //shop为实体类
        Shop shop = null;
        try {
            Boolean isLock = tryLock(LOCK_SHOP_KEY + id);
            //4.2 判断是否获取成功
            if (!isLock) {
                //4.3 失败,则休眠并重试
                Thread.sleep(50);
                return queryWithPassThrough(id);
            }
            //4.4 成功,根据id查询数据库
            shop = getById(id);
            //5. 不存在 返回错误
            if (shop == null) {
                // 将空值放入redis
                stringRedisTemplate.opsForValue().set(key, "", CACHE_NULL_TTL, TimeUnit.MINUTES);
                return null;
            }
            // 6. 存在 写入 redis
            stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(shop), CACHE_SHOP_TTL, TimeUnit.MINUTES);

        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            //7.释放互斥锁
            unLock(LOCK_SHOP_KEY + id);
        }

        //8.返回
        return shop;
    }

你可能感兴趣的:(redis,缓存,redis,数据库)