当前位置: 首页 > 知识库问答 >
问题:

java - 为什么Java通过redisTemplate使用Pipeline批量查询拿到的值都是空?

封景曜
2024-03-01

redisTemplate使用Pipeline批量查询,返回的结果全是null,keys集合是有数据的,redis里也是有数据的

public <T> List<T> batchGetList(Collection<String> keys) {        List<T> list = new ArrayList<>();        if (CollectionUtil.isEmpty(keys)) {            return list;        }        // 自定义序列化        RedisSerializer stringSerializer = redisTemplate.getStringSerializer();        RedisSerializer valueSerializer = redisTemplate.getValueSerializer();        RedisSerializer defaultSerializer = redisTemplate.getDefaultSerializer();        List result = redisTemplate.executePipelined(new RedisCallback<Object>() {            @Override            public Object doInRedis(RedisConnection connection) throws DataAccessException {                for (String k : keys) {                    System.err.println(k);                    byte[] bytes = connection.get(stringSerializer.serialize(k));                    byte[] bytes1 = connection.get(defaultSerializer.serialize(k));                    byte[] bytes2 = connection.get(valueSerializer.serialize(k));                    System.err.println(Arrays.toString(bytes));                    System.err.println(Arrays.toString(bytes1));                    System.err.println(Arrays.toString(bytes2));                    Object deserialize = defaultSerializer.deserialize(bytes);                    System.err.println(deserialize);                    list.add((T) deserialize);                }                return null;            }        }, redisTemplate.getValueSerializer());        return list;    }

image.png

换了一种方式,返回还是null

public <T> List<T> batchGetList1(Collection<String> keys) {        List<T> list = new ArrayList<>();        if (CollectionUtil.isEmpty(keys)) {            return list;        }        List result = redisTemplate.executePipelined(new SessionCallback<Object>() {            @Override            public Object execute(RedisOperations operations) throws DataAccessException {                keys.forEach(key->{                    System.err.println(key);                    Object o = operations.opsForValue().get(key);                    System.err.println(o);                    list.add((T) o);                });                return null;            }        });        return list;    }

image.png

共有1个答案

松和安
2024-03-01

在使用Spring Data Redis的RedisTemplate进行批量操作时,如果遇到使用管道(Pipeline)查询但返回的结果全是null,同时确认keys集合中确实有数据并且Redis中也有对应的数据,这通常是由于对管道操作的结果处理不当导致的。

首先,需要明白在使用管道技术时,Redis命令的执行结果不会立即返回。所有的命令都会被缓存起来,直到调用executePipelined方法时才一次性发送给Redis服务器,而executePipelined方法本身会返回一个包含每个命令响应的List。这就是为什么你的第一个示例方法中尝试在管道操作内部处理命令结果(例如直接反序列化)不会奏效的原因。管道操作完成后,你应该处理executePipelined返回的结果列表。

此外,你的第一个方法示例中尝试在循环内对每个键进行获取并反序列化,这实际上违背了使用管道的初衷,因为这样做并没有减少网络往返次数,而且实际上doInRedis方法的返回值应该被用来处理所有命令的结果。

对于第二个示例,正确的做法是在executePipelined之后处理结果,而不是在管道操作内部。

public <T> List<T> batchGetList(Collection<String> keys) {    if (CollectionUtil.isEmpty(keys)) {        return new ArrayList<>();    }    List<Object> results = redisTemplate.executePipelined((RedisConnection connection) -> {        RedisSerializer<String> keySerializer = (RedisSerializer<String>) redisTemplate.getKeySerializer();        for (String key : keys) {            connection.get(keySerializer.serialize(key));        }        return null;    });    // 在管道执行外部处理结果    return results.stream()                  .map(result -> (T) redisTemplate.getValueSerializer().deserialize((byte[]) result))                  .collect(Collectors.toList());}

这个方法发送所有的GET命令作为一个批量操作,并在操作完成后一次性处理所有的结果。请注意,这里假设所有键对应的值都是可以使用相同的反序列化器反序列化的。如果你的应用场景中有不同类型的值,你可能需要对结果进行进一步的处理来正确地反序列化它们。

 类似资料:
  • 问题内容: 我想问问为什么Java注释使用了这么多…我知道它们在例如jpa中替换了xml配置,但是为什么要使用这种配置呢?考虑这段代码: 现在,当我尝试使用的persist方法将其置于持久性上下文中时,尝试持久化实例会遇到运行时错误(最好是出现编译错误)。对我来说,有一个明显的解决方案,强制实体实现某种无方法接口,而不是使用@Annotations。但这在框架设计人员中并不流行,此解决方案的缺点是

  • 最近我遇到了一个问题:几乎没有sqlite查询在工作。请注意,插入等其他操作正在运行。我在StackOverflow和其他网站上读过很多不同的答案,但都不管用。 我的代码很简单: 当我在SQLite浏览器中执行时,一切都很正常。但是Java没有输出例外。

  • 问题内容: 我正在使用LLBLGEN,这里有一种方法可以将查询执行为。谷歌搜索给我一个定义,它们是一样的吗? 问题答案: 标量查询是一种返回由一列组成的一行的查询。

  • 本文向大家介绍详解Java使用Pipeline对Redis批量读写(hmset&hgetall),包括了详解Java使用Pipeline对Redis批量读写(hmset&hgetall)的使用技巧和注意事项,需要的朋友参考一下 一般情况下,Redis Client端发出一个请求后,通常会阻塞并等待Redis服务端处理,Redis服务端处理完后请求命令后会将结果通过响应报文返回给Client。 感觉

  • 问题内容: 我当前正在使用Elasticsearch V2.3.1。我想在Java中使用以下Elasticsearch查询。 上面的查询搜索名为“ kimchy”的“用户”,并使用给定值更新“列表”字段。该查询同时更新多个文档。我在https://www.elastic.co/guide/en/elasticsearch/client/java- api/2.3/java-docs- update

  • 问题内容: 我只是想知道为什么我们通常在两个布尔之间使用逻辑 而不是按位,尽管它们都运行良好。 我的意思是,请看以下内容: | | 我们可以|代替使用||吗?与&和相同&&。 问题答案: 如果使用和形式,而不是这些运算符的和形式,则Java不会费心地单独评估右手操作数。 多数情况下,是否要缩短评估是一个问题。 说明短路好处的一个好方法是考虑以下示例。 正如Jeremy和Peter提到的,短路的另一