I would like to retrieve multiple hashmap values with only specified fields. So I opted-in to Redis pipeline.
While testing the below code, i see redisResponse1
is always null, where as redisResponse2
has value.
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;
}
});
When I look into the code and found that below, where
a) redisResponse2
is not executed with pipeline option
b) redisResponse1
is executed with pipeline (isPipelined() == true) but returning always 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);
}
}
So questions are
1) How do I achieve my use case with pipeline option?
2) What is the impact accessing getRedisTemplate().getConnectionFactory().getConnection()
within this RedisCallback?
3) How this whole pipeline concept is working? Is it like dynamic Lua? where this Java code is converted as Lua script and send to Redis as script, executed in Redis and come back? Surprised on within this callback; the code is accessing/updating the outer class variables as well, so what will happen to all that variables? All those outer class variables also send to redis in lua?
4) I see many examples about doInRedis
API is returning null
; Why so? How to return/get valid Object from that?
The majority of your questions are available within the Spring Data Redis reference documentation.
Before digging into Pipelining, a single multi-get from one Hash does not require Pipelining because it's only a single command. Pipelining won't improve performance/stability/… of your Redis interaction.
Pipelining is arranged as callback and intended to issue multiple commands without awaiting the result immediately – think of it as a batch where you get all results later. Because pipelining synchronizes responses at the very end, you don't receive result values within the callback but at the very end, when the pipelining session is synchronized and
executePipelined(…)
terminates.Your code should rather look like:
You have to use only the connection that you receive as callback argument because the connection has entered pipelining mode. Obtaining a connection from outside the callback (like
template.getConnectionFactory().getConnection()
) will open a new connection and execute Redis commands with awaiting responses – no pipelining is applied to any external obtained connection.You can also use methods of
RedisTemplate
instead of working with the plain connection.executePipelined(…)
binds the connection used in the callback to the current Thread and reuses that bound connection if you call template API methods.Regarding your Lua question: The code/method calls are not transposed to Lua.