CacheContext

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;

import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
public class CacheContext<K, T> {
    // 占位符标志空数据
    public static final String DEFALT_VALUE = "#";

    private Jedis jedis;
    // 查询id
    private List<K> queryData;
    // 未命中缓存id
    private List<K> missData;
    // 返回class
    private Class<T> clazz;
    // 通过返回类型获取获取查询key方法
    private Function<T, K> getKeyFunction;
    // 查询key转换成rediskey方法
    private Function<K, String> keyMapping;
    // 查询原数据方法
    private Function<List<K>, List<T>> queryOriginFunction;
    // redis缓存时间 单位秒
    private int expireTime;
    // 最后结果
    private Map<K, T> res;


    public CacheContext(Jedis jedis, List<K> queryData, Class<T> returnClass, int expireTime, Function<K, String> keyMapping, Function<T, K> getKeyFunction, Function<List<K>, List<T>> queryOriginFunction) {
        this.jedis = jedis;
        this.queryData = queryData;
        this.keyMapping = keyMapping;
        this.clazz = returnClass;
        this.getKeyFunction = getKeyFunction;
        this.queryOriginFunction = queryOriginFunction;
        this.expireTime = expireTime;
        missData = Lists.newArrayList();
        res = Maps.newHashMap();
    }

    public void queryRedis() {
        //得到redis查询key
        String[] keys = queryData.stream().map(keyMapping).toArray(String[]::new);

        List<String> values = jedis.mget(keys);
        for (int i = 0; i < keys.length; i++) {
            String s = values.get(i);
            //未命中加入miss列表
            if (s == null) missData.add(queryData.get(i));
                // 说明数据库没有该记录
            else if (s.equals(DEFALT_VALUE)) continue;
                // 反序列化
            else {
                res.put(queryData.get(i), JSONObject.parseObject(s, clazz));
            }
        }
    }

    public Map<K, T> queryOrigin() {
        Map<K, T> originMap = Maps.newHashMap();
        // 没有miss 直接返回
        if (CollectionUtils.isEmpty(missData)) {
            return originMap;
        }
        // missData
        List<T> list = queryOriginFunction.apply(missData);
        list = list == null ? Lists.newArrayList() : list;
        Map<K, T> originRes = list.stream().collect(Collectors.toMap(getKeyFunction, Function.identity(), (o1, o2) -> o1));
        //查库没有的 也要用map记录下来 回填默认值
        for (K missDatum : missData) {
            T t = originRes.get(missDatum);
            originMap.put(missDatum, t);
            if (t != null) res.put(missDatum, t);
        }
        return originMap;
    }

    public void storeCache(Map<K, T> waitStore) {
        if (CollectionUtils.isEmpty(waitStore)) return;
        Pipeline pipelined = jedis.pipelined();
        try {
            for (Map.Entry<K, T> entry : waitStore.entrySet()) {
                K key = entry.getKey();
                T value = entry.getValue();
                if (value == null) pipelined.setex(keyMapping.apply(key), expireTime, DEFALT_VALUE);
                else pipelined.setex(keyMapping.apply(key), expireTime, JSONObject.toJSONString(value));
            }
        } catch (Exception e) {
            log.error("[[title={}]],fail,waitStore = {}", "storeCache", JSONObject.toJSONString(waitStore));
        } finally {
            pipelined.sync();
        }
    }

    public Map<K, T> getList() {
        // redis查询
        queryRedis();
        // 源头查询
        Map<K, T> originMap = queryOrigin();
        // 回写redis
        storeCache(originMap);
        return res;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值