Redis竞争锁失败异步获取兜底优化

优化前

//返回对象
Object result = null;
//分布式锁
String cacheLock = CacheUtil.genLockKey(cacheKey);
 
if (lock.lock(cacheLock, 5000, TimeUnit.MILLISECONDS)) {
    try {
        //业务方法查询逻辑
        result = pjp.proceed();
 
        if (Objects.nonNull(result)) {
            rwxCache.set(cacheKey, JSON.toJSONString(result), 1, TimeUnit.HOURS);
        }
    } catch (Exception e) {
        e.printStackTrace();
        rwxCache.del(cacheKey);
    } finally {
        lock.unlock(cacheLock);
    }
} else {
    Future<String> future = taskExecutor.submit(() -> rwxCache.get(cacheKey));
 
    try {
        cache = future.get(500, TimeUnit.MILLISECONDS);
        result = JSON.parseObject(cache, getReturnType(pjp));
    } catch (Exception e) {
        //important! 这里会有问题,一旦future超时,返回的是Object result = null;则没有信息返回,而此时是有可能有值的,应该抛出异常,而不是给一个不确定的结果
        e.printStackTrace();
        rwxCache.del(cacheKey);
    }
}
return result;

优化后

//返回对象
Object result = null;
//防止缓存穿透
//           rwxCache.set(cacheKey, CacheUtil.EMPTY, 1, TimeUnit.HOURS);
//分布式锁
String cacheLock = CacheUtil.genLockKey(cacheKey);
 
if (lock.lock(cacheLock, 5000, TimeUnit.MILLISECONDS)) {
    LOGGER.debug("[CacheFilterAspect] cache lock get. key={}", cacheKey);
    try {
        //业务方法查询逻辑
        result = pjp.proceed();
 
        if (Objects.nonNull(result)) {
            rwxCache.set(cacheKey, JSON.toJSONString(result), 1, TimeUnit.HOURS);
        }
    } catch (Exception e) {
        e.printStackTrace();
        rwxCache.del(cacheKey);
    } finally {
        lock.unlock(cacheLock);
    }
} else {
    LOGGER.info("[CacheFilterAspect] cache async get. key={}", cacheKey);
     
    Future<String> future = taskExecutor.submit(() -> {
        //如果分布式锁一直lock状态就进行自旋轮询,每隔Thread.sleep(10)毫秒轮询一次结果,future.get(500, TimeUnit.MILLISECONDS)除以Thread.sleep(100)就是轮询次数,超时则抛出异常
        while (true) {
            if (!lock.isLocked(cacheLock)) {
                return rwxCache.get(cacheKey);
            } else {
                try {
                    //这里会影响tp999等SLA指标,比如时间间隔太短设置5ms,cpu空转锁没释放请求redis过于频繁造成浪费;设置时间间隔太长则tp999飙高,而且锁释放了还没发起请求,这里根据tp999情况适当设置即可
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    LOGGER.error("[CacheRemoveAspect] interval wait error.", e);
                    //发生异常,则抛出异常,不返回明确结果
                    throw e;
                }
            }
        }
    });
 
    try {
        //这里是极端情况下max的值
        cache = future.get(500, TimeUnit.MILLISECONDS);
        result = JSON.parseObject(cache, getReturnType(pjp));
    } catch (Exception e) {
        e.printStackTrace();
        LOGGER.error("[CacheFilterAspect] cache async get timeout failed.");
        //发生异常,则抛出异常,不返回明确结果
        throw e;
    }
}
return result;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大摩羯先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值