黑马点评的总结(还在更新...)

黑马点评的总结和反思

1.缓存穿透

问题的体现

*下面就是我们的解决的方法(一旦查询到一次不存在的值,就往redis里面放入我们的空字符串这样下次访问无效的数据就可以使用redis来返回空字符串来防止数据库的损伤)

下面就是解决方案(直接给出最终的工具类因为工具类就可以通用了)

2.解决缓存击穿

问题的体现

解决思路

实现的思路

也是使用工具类的解决方法

首先我创建了一个类里面有我们一个新的字段就是逻辑过期的时间的设置RedisDate

// TODO 防止缓存击穿的线程池
    // TODO 成功 就开启一个线程(实现缓存重建)
    // 使用线程池来开启线程(10个线程)
    private static final ExecutorService CACHE_REBUILD_EXECUTOR = 																				Executors.newFixedThreadPool(10);
 /**
     * 这也是防止缓存击穿(设置的逻辑过期)
     *
     * @param keyPrefix  表示前缀
     * @param id         表示我们要查询数据库的id
     * @param type       表示我们从redis中的得到的数据转为什么java对象
     * @param dbFallback 函数式方程
     * @param time       设置过期的时间
     * @param unit       设置过期的单位
     * @param <R>        这个就是我们的返回值
     * @param <ID>       这个就是我们id的类型
     * @return
     */
    public <R, ID> R queryWithLogiclExpire(
            String keyPrefix, ID id, Class<R> type, Function<ID, R> dbFallback, Long 																  time, TimeUnit unit) {

        String key = keyPrefix + id;

        // 取redis中的缓存
        String jsonStr = stringRedisTemplate.opsForValue().get(key);

        // 进了这个判断就是没有命中
        if (StrUtil.isBlank(jsonStr)) {  //isNotBlank 不为空就是true
            return null;
        }

        // 命中需要json反序列化
        RedisData redisData = JSONUtil.toBean(jsonStr, RedisData.class);
        // 获取我们的数据
        // 得到我们的jsonObject
        JSONObject data = (JSONObject) redisData.getData();
        // 得到我们json对象
        R r = JSONUtil.toBean(data, type);

        // 获取过期时间(逻辑过期时间)
        LocalDateTime expireTime = redisData.getExpireTime();

        // 再来判断是否过期(过期时间是不是在当前时间之后喃)
        if (expireTime.isAfter(LocalDateTime.now())) {
            // 没有过期直接返回
            return r;
        }
        // 如果已经过期 我们就要进行缓存重建
        String lockKey = LOCK_SHOP_KEY + id;
        // 获取互斥锁
        boolean isLock = tryLock(lockKey);
        // 判断获取锁是否成功
        if (isLock) {
            // TODO 成功 就开启一个线程(实现缓存重建)
            // 提交任务
            CACHE_REBUILD_EXECUTOR.submit(() -> {
                try {
                    // TODO 重建缓存
                    // 第一步查询数据库
                    R r1 = dbFallback.apply(id);

                    // 写入redis(并且使用的是逻辑过期)
                    this.setWithLogiclExpire(key, r1, time, unit);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                } finally {
                    // 重建缓存后就要释放锁
                    unlock(lockKey);
                }

            });
        }
        // 不成功就返回当前的数据(也就是旧数据)

        // 返回
        return r;
    }

下面是我们利用锁(也是利用了redis的一个特性)

关闭锁当然也就很简单了

3.秒杀的一些处理(这个很重要就是处理我们的分布式)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值