Spring Data Redis:Redis Pipeline始终返回null

5
我想通过只指定字段来检索多个哈希映射值,因此我选择了Redis管道。
在测试下面的代码时,我发现 redisResponse1 始终为空,而 redisResponse2 有值。
    getRedisTemplate().executePipelined(new RedisCallback<Object>() { 
        @Override
        public Object doInRedis(RedisConnection connection) throws DataAccessException {
                List<byte[]> redisResponse1 = connection.hMGet(key.getBytes(), params);
                List<byte[]> redisResponse2 = getRedisTemplate().getConnectionFactory().getConnection().hMGet(key.getBytes(), specificParams);
                return null;
        }
    });

当我查看代码并发现以下内容时,其中:
a) redisResponse2 没有使用 pipeline 选项执行

b) redisResponse1 使用 pipeline 执行(isPipelined() == true),但始终返回 null。

public List<byte[]> hMGet(byte[] key, byte[]... fields) {
    try {
        if (isPipelined()) {
            pipeline(new JedisResult(pipeline.hmget(key, fields)));
            return null;
        }
        if (isQueueing()) {
            transaction(new JedisResult(transaction.hmget(key, fields)));
            return null;
        }
        return jedis.hmget(key, fields);
    } catch (Exception ex) {
        throw convertJedisAccessException(ex);
    }
}

问题如下:

1)如何使用管道选项实现我的用例?

2)在这个RedisCallback中访问getRedisTemplate().getConnectionFactory().getConnection()会有什么影响?

3)整个管道的概念是如何工作的?它像动态Lua一样吗?Java代码被转换为Lua脚本并作为脚本发送到Redis,在Redis中执行并返回?惊讶于在这个回调中,代码还访问/更新外部类变量,那么所有这些变量会发生什么?所有这些外部类变量也会在Lua中发送到Redis吗?

4)我看到很多关于doInRedis API返回null的示例;为什么会这样?如何从中返回/获取有效的对象?


使用 spring-data-redis-1.6.6.RELEASE.jar。 - Kanagavelu Sugumar
2个回答

6
大多数问题都可以在Spring Data Redis 参考文档中找到。
在深入了解管道技术之前,从一个哈希表中获取多个值不需要使用管道技术,因为它只是一个单一的命令。使用管道技术不能改善Redis交互的性能/稳定性/等等。
管道技术被安排为回调函数,旨在发出多个命令而不立即等待结果 - 将其视为批处理,在稍后获取所有结果。由于管道技术在最后同步响应,因此您不会在回调函数中收到结果值,而是在管道技术会话同步并且executePipelined(…)终止时收到结果。
您的代码应该像这样:
List<Object> results = getRedisTemplate().executePipelined(new RedisCallback<Object>() {

    @Override
    public Object doInRedis(RedisConnection connection) {

            connection.hMGet(key.getBytes(), params);

            return null;
    }
});

List<Object> hmget = (List<Object>) results.get(0);

您需要仅使用作为回调参数接收的连接,因为该连接已进入流水线模式。从回调外部获取连接(如template.getConnectionFactory().getConnection())将打开新连接并执行Redis命令以等待响应 - 不会对任何外部获取的连接应用流水线。
您还可以使用RedisTemplate的方法,而不是使用普通连接。 executePipelined(…)将回调中使用的连接绑定到当前线程,并在调用模板API方法时重用该绑定连接。
关于您的Lua问题:代码/方法调用不会转换为Lua。

@mp911de 这个话题与 Redis 有关,但是偏离了主题。如果您对此链接(https://stackoverflow.com/q/57572975/3110101?stw=2)有任何信息,我将不胜感激。 - pan1490

0
关于问题:
  1. 我看到很多关于doInRedis API返回null的例子;为什么会这样?如何从中返回/获取有效的对象?

以下是答案:

https://docs.spring.io/spring-data/redis/docs/current/reference/html/#pipeline

//pop a specified number of items from a queue
List<Object> results = stringRedisTemplate.executePipelined(
  new RedisCallback<Object>() {
    public Object doInRedis(RedisConnection connection) throws DataAccessException {
      StringRedisConnection stringRedisConn = (StringRedisConnection)connection;
      for(int i=0; i< batchSize; i++) {
        stringRedisConn.rPop("myqueue");
      }
    return null;
  }
});

请注意,从RedisCallback返回的值必须为null,因为该值被丢弃以返回管道命令的结果。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接