Spring 数据 Redis:Redis 管道始终返回 null
Spring Data Redis: Redis Pipeline returning always null
我想检索仅包含指定字段的多个散列映射值。所以我选择了 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 中执行然后返回?在此回调中感到惊讶;代码也是 accessing/updating 外部 class 变量,那么所有这些变量会发生什么?所有这些外部 class 变量也在 lua 中发送到 redis?
4) 我看到很多关于 doInRedis
API 返回 null
的例子;为什么这样?如何从中 return/get 有效对象?
您的大部分问题都可以在 Spring Data Redis reference documentation.
中找到
在深入研究流水线之前,来自一个哈希的单个多获取不需要流水线,因为它只是一个命令。流水线不会改善 performance/stability/... 您的 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 问题:code/method 调用未转换为 Lua。
我想检索仅包含指定字段的多个散列映射值。所以我选择了 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 中执行然后返回?在此回调中感到惊讶;代码也是 accessing/updating 外部 class 变量,那么所有这些变量会发生什么?所有这些外部 class 变量也在 lua 中发送到 redis?
4) 我看到很多关于 doInRedis
API 返回 null
的例子;为什么这样?如何从中 return/get 有效对象?
您的大部分问题都可以在 Spring Data Redis reference documentation.
中找到在深入研究流水线之前,来自一个哈希的单个多获取不需要流水线,因为它只是一个命令。流水线不会改善 performance/stability/... 您的 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 问题:code/method 调用未转换为 Lua。