使用Redisson实现高并发场景下的缓存穿透、缓存击穿、缓存雪崩以及缓存数据不一致性的问题

使用Redisson实现高并发场景下的缓存穿透、缓存击穿、缓存雪崩以及缓存数据不一致性的问题

  1. 缓存击穿:同一时间进行查询,缓存中没有找到,查询数据库,可以通过设置不同的过期时间解决
  2. 缓存穿透:同一时间进行查询,缓存中没有找到,数据库中也没有查到,可以通过设置空对象解决
  3. 缓存雪崩:缓存宕机了,加一个map保存对象,从缓存中查询前先从map中查询
  4. 缓存与数据库不一致:对更新数据加写锁,对读数据加读锁解决

以下核心代码涉及到商品的更新以及查看,解决高并发下的缓存的问题

private static Map<String,Product> productMap = new ConcurrenHashMap<>();
 // 更新
  @Transactional
  public Product update(Product product) {
    Product productResult = null;
    // 解决高并发场景下查看和更新是数据库和缓存数据不一致的问题 使用写锁
    RReadWriteLock readWriteLock = redisson.geReadWritetLock(LOCK_PRODUCT_UPDATE_PREFIX + product.getId());
    RLock writeLock = readWriteLock.writeLock();
    writeLock.lock();
    try {
      productResult = productDao.update(product);
      redisutil.set(RedisKeyPrefixConst.PRODUCT_CACHE + productResult.getId(), JSON.toJS0NString(productResult),
              genProductcacheTimeout(), TimeUnit.SECONDS);
      productMap.put(RedisKeyPrefixConst.PRODUCT_CACHE + productResult.getId(),product);
    } finally {
      writeLock.unlock();
    }
    return productResult;
  }

  // 查看
  public Product get(Long productId) {
    Product product = null;
    String productCacheKey = RedisKeyPrefixConst.PRODUCT_CACHE + productId;
    // 从缓存中获取
    product = getProductFromCache(productCacheKey);
    if (product != null) {
      return product;
    }
    // 高并发分布式锁
    RLock hotCacheLock = redisson.getLock(productCacheKey+productId);
    hotCacheLock.lock();
    // 知道业务处理时间进行优化
//    hotCacheLock.tryLock(3, TimeUnit.SECONDS);
    try {
      product = getProductFromCache(productCacheKey);
      if (product != null) {
        return product;
      }
      // 解决高并发场景下查看和更新 数据库和缓存数据不一致的问题 使用读锁
      RReadWriteLock readWriteLock = redisson.geReadWritetLock(LOCK_PRODUCT_UPDATE_PREFIX + productId);
      RLock readLock = readWriteLock.readLock();
      readLock.lock();
      try {
        product = productDao.get(productId);
        if (product != null) {
          // 解决缓存穿透问题:缓存过期时间随机
          redisUtil.set(productCacheKey, JSON.toJsONString(product), genProductCacheTimeout(), TimeUnit.SECONDS);
          // 解决缓存雪崩问题
          productMap.put(productCacheKey,product);
        } else {
          // 解决缓存穿透问题
          redisUtil.set(productCacheKey, "{}");
        }
      }finally {
        readLock.unlock();
      }
    }finally {
      hotCacheLock.unlock();
    }
    return product;
  }

  //获取随机过期时间
  private Integer genProductCacheTimeout() {
    return PRODUCT_CACHE_TIMEOUT + new Random().nextInt(5) *60 * 60;
  }
  // 抽取缓存获取数据方法
  private Product getProductFromCache(String productCacheKey) {
    Product product = null;
    // 从map中取值
    product = productMap.get(productCacheKey);
    if(Objects.nonNull(product)){
    	return product;
    }
    String productstr = redisutil.get(productCacheKey);
    if (!stringutils.isEmpty(productStr)) {
      if (EMPTY_CACHE.equals(productstr)) {
        return new Product();
      }
      product = JSON.parseObject(productstr, Product.class);
      redisUtil.expire(productCacheKey,genProductCacheTimeout(productCacheKey,genProductCacheTimeout(),TimeUnit.SECONDS); //缓存读延期
    }
    return product;
  }
  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值