redis+guava 实现多级缓存

JAVA 基础体系


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

前言

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

场景与使用:

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

首先要注意,为防止缓存击穿,我们不能依赖用户请求来获取配置,及时加锁也不行,在交易链路使用分布式锁阻断了交易就很坑。 所以,我们后台起个TASK将数据跑入redis,缓存时间设置了3天防止过期。

  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();
    }

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

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章