Redis系列05 - redis+guava实现多级缓存

JAVA 基础体系

      • 前言
      • 场景与使用:

虽然面对的是高并发场景,单今天只关注缓存,不讨论线程安全和锁相关的问题。

前言

日常工作中,时常要面对抽奖活动,奖励发放,商品秒杀等大流量高并发的场景。
高并发场景面对的第一个问题是DB的IO瓶颈。 这时比较通用的方式是加缓存对DB进行加速与保护,用redis对内存的性能来解决IO的瓶颈。
但是引入Redis就一劳永逸了嘛?不是的,相对应的高并发场景又会引发Redis热KEY和大KEY的问题,造成带宽拉胯。
这时需要再做一层本地缓存。那么问题又来了,本地缓存没有过期时间等限制,现在可以用GUAVA CACHE来解决,本质上他就是封装了一个过期时间,至于过期策略,一般有三种,定时删除,定期删除,惰性删除。guava本地缓存就是采用惰性删除的方式就很合理。感兴趣的同学,可以看下教程和源码http://ifeve.com/google-guava,这里不具体展开了。
附一张关键源码图:
Redis系列05 - redis+guava实现多级缓存_第1张图片

场景与使用:

场景一:动态配置获取, 交易链路,需要获取商家报名了活动,报名与否,会走不同的优惠策略。

首先要注意,为防止缓存击穿,我们不能依赖用户请求来获取配置,即使加锁也不行,优惠是要强校验的,使用分布式锁就阻断了交易。 所以,我后台起个Task将数据跑入redis,缓存时间设置了3天防止过期,任务10分钟1次。下面是使用的场景

  private List<Long> getSignupSellerUids(Long sellerActivityId) {
        // 报名商家sellerUid 本地缓存
        List<Long> localSignedupUids =
            signupUidsLocalCache.getIfPresent(AllowanceConstant.ALLOWANCE_SIGNEDUP_SELLERS_CACHE_KEY);
        if (Validator.isNotNull(localSignedupUids)) {
            return localSignedupUids;
        }

        // 本地没命中 走Redis缓存
        String signedUpCacheKey = BeidianAllowanceCacheUtils.getSignedUpSellersCacheKey(sellerActivityId);
        String confJsonStr = beidianRedisCacheClient.get(signedUpCacheKey);
        List<Long> cacheSignedUids = Validator.isNotNullOrEmpty(JSON.parseArray(confJsonStr, Long.TYPE)) ?
            JSON.parseArray(confJsonStr, Long.TYPE) :
            Collections.emptyList();
        if (!cacheSignedUids.isEmpty()) {
            
			// 获取到数据后,优先记录进本地缓存
            signupUidsLocalCache.put(AllowanceConstant.ALLOWANCE_SIGNEDUP_SELLERS_CACHE_KEY, cacheSignedUids);
            return cacheSignedUids;
        }

        // 这里已经是异常状态了。
        return Collections.emptyList();
    }

场景二:首页商品的ES数据,整体数据很多,又有千人千面, 所以可以单独用Guava做一层当商品维度(商品iid维度)的缓存。

        List<String> iidCacheKeyList = new ArrayList<>();
        for (Object iid : beidianESCacheKeyBO.getIidList()) {
            iidCacheKeyList.add(getSingleItemESCacheKey(beidianESCacheKeyBO.getBaseItemESCacheKey(), iid));
        }
        Map<String, SearchItemTO> singleItemCacheMap = beidianSingleItemESCache.getAllPresent(iidCacheKeyList);

一些会随业务变化的动态配置,都非常适合使用多级缓存,让你的程序稳稳当当哟~

没有试过的小伙伴,一定要去试一试O(∩_∩)O

你可能感兴趣的:(Redis,guava,缓存,redis,缓存,java)