首页 > 数据库 >redis批量先查缓存再查数据库

redis批量先查缓存再查数据库

时间:2023-09-15 17:09:30浏览次数:42  
标签:再查 缓存 return redis List params result queryKeys 先查

RedisUtil:

/**
     *  批量查询缓存,若是缓存没有的数据再调用对应的方法查询数据,查询之后放入缓存
     * @param prefix 缓存前缀
     * @param params 缓存参数
     * @param column 缓存参数对应字段列名
     * @param dataBaseFunction 数据库查询方法
     * @return
     * @param <T> 查询参数
     * @param <R> 返回类型
     */
    public  <T,R> List<R> batchGetCacheData(String prefix, Collection<T> params, String column,
                                            Function<Set<T>,List<R>> dataBaseFunction, Class<R> clazz){
        // TODO 未大规模测试 暂时不使用
        //       先查redis
        Set<String> keys = params.stream().map(m -> {return prefix + m;}).collect(Collectors.toSet());
        List<String> cacheResultList = new ArrayList<>();
        List<List<T>> splitList = ListUtil.split((Collection<T>) keys, 500);
        for (List<T> ts : splitList) {
            cacheResultList.addAll(redisTemplate.executePipelined(new RedisCallback<String>() {
                @Override
                public String doInRedis(RedisConnection connection) throws DataAccessException {
                    for (T key : ts) {
                        connection.get(key.toString().getBytes());
                    }
                    return null;
                }
            }));
        }
        //过滤出没有获取到缓存的数据,去执行对应数据库查询
        Tuple2<Set<T>, List<R>> tuple2 = analysisCacheVal(params, cacheResultList, clazz);
        Set<T> queryKeys = tuple2.getFirst();
        List<R> result = tuple2.getSecond();
        if(!CollectionUtils.isEmpty(result) && result.size() == params.size()){
            return result;
        }
        List<R> dataBaseResult = getDataBaseFunction(prefix, queryKeys, dataBaseFunction, column);
        result.addAll(dataBaseResult);
        return result;
    }

    private static <T,R> Tuple2<Set<T>, List<R>> analysisCacheVal (Collection<T> params, List<String> cacheResultList, Class<R> clazz) {
        Set<T> queryKeys = new HashSet<>();
        List<R> result = new ArrayList<>();
        T[] paramsObj = (T[]) params.toArray();
        for (int i = 0; i< params.size(); i++) {
            String cacheR = cacheResultList.get(i);
            if (Objects.isNull(cacheR)) {
                queryKeys.add(paramsObj[i]);
            } else {
                result.add(JSON.parseObject(cacheR, clazz));
            }
        }
        return new Tuple2<>(queryKeys, result);
    }

    private <T,R> List<R> getDataBaseFunction (String prefix, Set<T> queryKeys, Function<Set<T>,List<R>> dataBaseFunction, String column) {
        List<R> dataBaseResult = dataBaseFunction.apply(queryKeys);
        if(!CollectionUtils.isEmpty(dataBaseResult)){
            for (R r : dataBaseResult) {
                Object obj = getProperty(r, column);
                if (Objects.nonNull(obj)) {
                    redisTemplate.opsForValue().set(prefix + obj.toString(), JSON.toJSONString(r), 1, TimeUnit.MINUTES);
                }
            }
        }
        return dataBaseResult;
    }


    public static <R> Object getProperty(R object, String column) {
        Class<?> clazz = object.getClass();
        Field[] fields = clazz.getDeclaredFields();

        for (Field field : fields) {
            if (field.getName().equals(column)) {
                try {
                    field.setAccessible(true);
                    return field.get(object);
                } catch (IllegalAccessException e) {
                    log.error("RedisUtil getProperty error {}", e);
                    return null;
                }
            }
        }
        return null;
    }

调用方式:redisUtil.batchGetCacheData("country:", ids, "id", v -> countryBiz.getByIds(ids), CountryVO.class);

ListUtil

 public static final int DEFAULT_LIMIT = 500;
    public static final int LIMIT1000 = 1000;

    public static <T> List<List<T>> split(Collection<T> collection) {
        return split(collection, DEFAULT_LIMIT);
    }

    public static <T> List<List<T>> split(Collection<T> collection, int size) {
        if (collection == null || collection.isEmpty()) {
            return Collections.emptyList();
        }
        List<T> list = new ArrayList<>(collection);
        final int listSize = list.size();
        final List<List<T>> result = new ArrayList<>(listSize / size + 1);
        int offset = 0;
        for (int toIdx = size; toIdx <= listSize; offset = toIdx, toIdx += size) {
            result.add(list.subList(offset, toIdx));
        }
        if (offset < listSize) {
            result.add(list.subList(offset, listSize));
        }
        return result;
    }

标签:再查,缓存,return,redis,List,params,result,queryKeys,先查
From: https://blog.51cto.com/u_13643129/7483558

相关文章

  • redis配置(二)
    1.redis扩展:redis服务可以使用相关程序写代码去连接服务.redis服务(可以理解为一个很屌的Socket服务端程序)________________________________________|||PHP扩展java相关客户端库调用python相关包调......
  • Redis SCAN:实现key的模糊匹配的科学方法
    目录scan基本介绍shell使用scan最基本的scan带匹配模式和count的scanjava中使用hscanscan基本介绍在使用redis的时候,我们经常涉及到这样的需求:模糊搜索key,即找出满足特定匹配模式的所有key。但是,如果使用像keys和hkyes这样的方法的话,当key的数量特别多时,效率会很慢,而且对线......
  • Redis高级客户端Lettuce详解
    Lettuce是一个高性能基于Java编写的Redis驱动框架,底层集成了ProjectReactor提供天然的反应式编程,通信框架集成了Netty使用了非阻塞IO,5.x版本之后融合了JDK1.8的异步编程特性,在保证高性能的同时提供了十分丰富易用的API,5.1版本的新特性如下:支持Redis的新增命令ZPOPMIN,ZPOPMAX,BZ......
  • 为什么我的Redis这么“慢”?
    为什么我的Redis这么“慢”?Redis作为内存数据库,拥有非常高的性能,单个实例的QPS能够达到10W左右。但我们在使用Redis时,经常时不时会出现访问延迟很大的情况,如果你不知道Redis的内部实现原理,在排查问题时就会一头雾水。很多时候,Redis出现访问延迟变大,都与我们的使用不当或......
  • redis-删除所有key
    删除所有Key,可以使用Redis的flushdb和flushall命令//删除当前数据库中的所有Keyflushdb//删除所有数据库中的keyflushall 如果要访问Redis中特定的数据库,使用下面的命令//下面的命令指定数据序号为0,即默认数据库redis-cli-n0keys"*"|xargsredis-cli-n0del ......
  • 本地缓存和Redis缓存
    Redis可以实现分布式的缓存,Map属于本地缓存,只能存在创建它的程序里Redis的缓存可以持久化,Map是内存对象,程序一重启数据就没了Redis缓存有过期机制,Map本身无此功能Redis可以处理每秒百万级的并发,是专业的缓存服务,Map只是一个普通的对象Redis可以用几十G内存来做缓存......
  • C# StackExchange.Redis使用
    RedisManage类管理类,提供Redis管理上下文,此处单例模式实现获取对应的Redis管理器usingStackExchange.Redis;namespaceDataMigrationService{publicclassRedisManage{publicstaticreadonlyConfigurationOptionsConfigurationOptions=Configurati......
  • Redis7 10大数据类型(Redis哈希)
    一、常用二、KV模式不变,V是一个键值对Map<String,Map<Object,Object>>三、案例1、hset/hget/hmset/hmget/hgetall/hdel2、hlen获取某个key内的全部数量3、hexistskey在key里面的某个值的key4、hkeys/hvals5、hincrby/hincrbyfloat6、hsetnx(不存在赋值,存在了无效)7、应用场景购......
  • 解读Redis常见命令
    Redis数据结构介绍Redis是一个key-value的数据库,key一般是String类型,不过value的类型多种多样:贴心小建议:命令不要死记,学会查询就好啦Redis为了方便我们学习,将操作不同数据类型的命令也做了分组,在官网:https://redis.io/commands可以查看到不同的命令:当然我们也可以通过Help......
  • Redis管道Batch操作
    管道Batch操作privateasyncTaskAddTTL(){vardb=RDDB.RedisAgent.Database;Stopwatchsp=Stopwatch.StartNew();varbatch1=db.CreateBatch();for(inti=0;i<1000000;i++){......