【问题标题】:Spring Data Redis: Redis Pipeline returning always nullSpring Data Redis:Redis 管道始终返回 null
【发布时间】:2018-03-01 13:44:00
【问题描述】:

我想检索多个仅包含指定字段的 hashmap 值。所以我选择了 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 不使用管道选项执行

b) redisResponse1 使用管道 (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

标签: java lua redis spring-data pipelining


【解决方案1】:

您的大部分问题都可以在 Spring Data Redis reference documentation 中找到。

在深入研究流水线之前,来自一个哈希的单个多获取不需要流水线,因为它只是一个命令。流水线不会提高 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 有关,如果您对此有任何信息,我将不胜感激link
猜你喜欢
  • 2023-03-17
  • 2018-02-12
  • 1970-01-01
  • 2016-05-31
  • 2015-08-15
  • 2012-03-18
  • 2016-11-04
  • 2016-07-28
  • 2010-11-08
相关资源
最近更新 更多