cache二级缓存增加性能

public abstract class Api<K, V> {

    /**
     * 设置最大缓存个数
     */
    int maximumSize = 2000;

    /**
     * 实例化缓存
     */
    LoadingCache<K, V> cache;


    /**
     * 初始化缓存(1个参数)
     *
     * @param expire 过期时间
     * @param function 1个参数
     */
    public Api(long expire, Function<K, V> function) {
        init(expire, function, null);
    }


    /**
     * 初始化缓存(2个以上的参数)
     *
     * @param expire 过期时间
     * @param biFunction 传入2个以上的参数
     */
    public Api(long expire, BiFunction<String, String, V> biFunction) {
        init(expire, null, biFunction);
    }


    /**
     * 初始化缓存
     *
     * @param expire     数据过期时间的值
     * @param function   传入函数
     * @param biFunction 传入多个参数
     */
    private LoadingCache<K, V> init(long expire, Function<K, V> function, BiFunction<String, String, V> biFunction) {
        Caffeine<Object, Object> cacheBuilder = Caffeine.newBuilder();
        // 基于大小-缓存大小,缓存最大条数,超过这个条数就是驱逐缓存
        cacheBuilder.maximumSize(maximumSize);
        // 这个参数是 LoadingCache 和 AsyncLoadingCache 的才会有的。在刷新的时候如果查询缓存元素,其旧值将仍被返回,直到该元素的刷新完毕后结束后才会返回刷新后的新值。
        // refreshAfterWrite 将会使在写操作之后的一段时间后允许 key 对应的缓存元素进行刷新,但是只有在这个 key 被真正查询到的时候才会正式进行刷新操作。
        // 在刷新的过程中,如果抛出任何异常,会保留旧值。异常会被 logger 打印,然后被吞掉。
        // 此外,CacheLoader 还支持通过覆盖重写 CacheLoader.reload(K, V) 方法使得在刷新中可以将旧值也参与到更新的过程中去。
        // refresh 的操作将会异步执行在一个 Executor 上。默认的线程池实现是 ForkJoinPool.commonPool()。当然也可以通过覆盖 Caffeine.executor(Executor) 方法自定义线程池的实现。
        // 这个 Executor 同时负责 removalListener 的操作。
        cacheBuilder.refreshAfterWrite(expire, TimeUnit.SECONDS);
        cache = cacheBuilder.build(
                key -> {
                    V value = null;
                    if (null != function) {
                        value = function.apply(key);
                    }
                    if (biFunction != null) {
                        String[] args = ((String) key).split(",");
                        value = biFunction.apply(args[0], args[1]);
                    }
                    return value;
                });
        return cache;
    }

    /**
     * 主动触发 loading
     *
     * @param key
     */
    public void refresh(K key) {
        try {
            if (null != cache && null != cache.get(key)) {
                cache.refresh(key);
            }
        } catch (Throwable ignore) {
            log.error(">>>>>>>> query from caffeine cache by key: " + key + ", get a null <<<<<<<<<<<<<", ignore);
        }
    }

    /**
     * 根据 key 查询的公共方法,没有特殊需求的话,统一走此方法获取数据
     *
     * @param key
     * @return
     */
    public V get(K key) {
        try {
            if (null != cache) {
                return cache.get(key);
            }
            return null;
        } catch (Throwable e) {
            log.error(">>>>>>>> query from caffeine cache by key: " + key + ", get a null <<<<<<<<<<<<<", e);
            return null;
        }
    }
}
@Log4j2
public abstract class ApiCache {

    public class Api0 extends Api {

        public Api0(long expire, Function<String, ?> function) {
            super(expire, function);
        }

        public Api0(long expire, BiFunction<String, String, ?> biFunction) {
            super(expire, biFunction);
        }
    }

    private Map<String, Api0> apis = new HashMap<>();

    protected void put(String cacheName, Function<String, ?> function,Long expire) {
        apis.put(cacheName, new Api0(expire, function));
    }

    protected void put(String cacheName, BiFunction<String, String, ?> function,Long expire) {
        apis.put(cacheName, new Api0(expire, function));
    }

    /**
     * @param type        业务类型 api key
     * @param key         缓存数据 key
     * @param returnClass 返回值类型
     * @param <V>
     * @return
     */
    public <V> V get(String type, String key, Class<V> returnClass) {
        //log.info(">>>>>>>>invoker:[" + "" + "] Caffeine get by key: " + key + " <<<<<<<<<<<<<" + UUID.randomUUID().toString());
        try {
            Api0 api01 = apis.get(type);
            if(null != api01){
                Object o = api01.get(key);
                return (V) o;
            }

        } catch (Throwable ignore) {
            log.error("ApiCache get error"+ ignore.getMessage(),ignore);
        }
        return null;
    }

    /**
     * 用于调试
     *
     * @return
     */
    public Map<String, Api0> getApis() {
        return apis;
    }

    public void refresh(String type, String key) {
        //log.info(">>>>>>>> api wrapper type:" + type + "] Caffeine cache has been refreshed by key: " + key + " <<<<<<<<<<<<<");
        try {
            Api0 api01 = apis.get(type);
            if(null != api01){
                api01.refresh(key);
            }

        } catch (Throwable ignore) {
            log.error("ApiCache refresh error"+ ignore.getMessage(),ignore);
        }
    }
}
@Component
@Order(value = 5)
public class CacheUserCosplayDataWrapper extends ApiCache implements CommandLineRunner {


    public static String USER_SELF_DATA_CACHE = "userSelfDataCache";
    public static String USER_OTHER_DATA_CACHE = "userOtherDataCache";

    @Autowired
    private UserCosplayDataService cosplayDataService;


    @Override
    public void run(String... args) throws Exception {
        //缓存设置 10秒超时
        super.put(USER_SELF_DATA_CACHE, cosplayDataService::getUserSelfDataByUserId, 3L);
        super.put(USER_OTHER_DATA_CACHE, cosplayDataService::getUserOtherDataByUserId, 3L);
    }
}
public UserOtherDataResponse getUserOtherDataByUserId(String userIdInfo) {
        List<String> userIds = Arrays.asList(userIdInfo.split("_"));
        Long otherUserId = Long.valueOf(userIds.get(0));

        UserOtherDataResponse response = new UserOtherDataResponse();
        // 查询用户信息
        CommonResult<UserBaseInfoResponse> userBaseInfoResult =
                userBaseInfoFeign.getUserBaseDetailInfoByUserId(new UserBaseInfoRequest(otherUserId));
        if (!userBaseInfoResult.getCode().equals(CommonResult.successResult().getCode())) {
            throw new BusinessException("查询他的主页失败");
        }
        // 拷贝用户信息(优化为空时候不拷贝)
        BeanUtil.copyProperties(userBaseInfoResult.getData(), response,
                CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        return response;
    }

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值