0

I am using Jedis for Accessing Redis via Spring Data.

<bean
    id="jedisPoolConfig"
    class="redis.clients.jedis.JedisPoolConfig"
    p:maxTotal="100"
    p:maxIdle="10"
    p:maxWaitMillis="5000"
/> 

<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
    p:host-name="${redis.server.host}" p:port="${redis.server.port}"
    p:password="${redis.server.password}" 
    p:use-pool="${redis.server.usepool}" 
    p:pool-config-ref="jedisPoolConfig"/>

<bean id="genericJackson2JsonRedisSerializer" class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>

<bean id="stringSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>       


<!-- redis template definition -->  
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"      p:connection-factory-ref="jedisConnectionFactory">      <property name="keySerializer" ref="stringSerializer"/>
        <property name="hashKeySerializer" ref="stringSerializer"/>
        <property name="hashValueSerializer" ref="genericJackson2JsonRedisSerializer"/>
</bean>     

<bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate"      p:connection-factory-ref="jedisConnectionFactory" />

Would like to perform BRPOPLPUSH, I dont see this option under

   OPTION_1  -> getRedisTemplate().boundListOps("Key").*

   OPTION_2 -> getRedisTemplate().opsForList().rightPopAndLeftPush("sourceKey", "destinationKey")  ---> No blocking ? 

Instead it is available at,

   OPTION_3 -> getRedisTemplate().getConnectionFactory().getConnection().bRPopLPush(timeout, srcKey, dstKey)



Question_0: Is this the only option? Why it is not available in above two api's?

Answer_0: No, whenever timeunit is mentioned with left/rightPop(timeout, unit) in boundListOps, opsForList it is blocking call. timeunit with 0 seconds for blocking for ever.

Question_1: Why there are so many variants ..? or May be when to use boundListOps, opsForList and getConnection?

Partial_Answer_1: Looks like if multiple operation to be acted upon a single key then boundListOps, because it is bound to that single key, and no need to mention that in the repeated actions, where as in opsForList, every action key has to be mentioned.

From doc of boundListOps:

Returns the operations performed on list values bound to the given key.

Just note that, boundListOps still uses opsForList inherently by passing the registered key to it.

Ok, still when should i use directly getConnectionFactory().getConnection() ?

Question_2: If i use getConnectionFactory().getConnection(), Do i need to close() this connection under finally(){}? (Since this is the one currently having blocking RPopLPush support).

From the code boundListOps is inherently using opsForList, and its all action are executed with finally like below with release connection, hence asked.

RedisTemplate.java
 public <T> T execute(RedisCallback<T> action, boolean exposeConnection, boolean pipeline) {
RedisConnectionFactory factory = getConnectionFactory();
        RedisConnection conn = null;
        try {
            conn = RedisConnectionUtils.getConnection(factory);
            ...
            ...
        // TODO: any other connection processing?
        return postProcessResult(result, connToUse, existingConnection);
        } finally {
            RedisConnectionUtils.releaseConnection(conn, factory);
        }

Question_3: Why getRedisTemplate().boundListOps("key").rightPush(new HashMap()); is accepting Map instead of value like String/Object though "key" is already mentioned...?

Answer_3: It is my problem, I have declared that way.

public RedisTemplate<String, Map<String, Object>> getRedisTemplate() {
        return redisTemplate;
}

And the same RedisTemplate object is passed as this while fetching DefaultBoundListOperations where V is referred from RedisTemplate.

public BoundListOperations<K, V> boundListOps(K key) {
    return new DefaultBoundListOperations<K, V>(key, this);
}

class DefaultBoundListOperations<K, V> extends DefaultBoundKeyOperations<K> implements BoundListOperations<K, V> {

    public DefaultBoundListOperations(K key, RedisOperations<K, V> operations) {
        super(key, operations); //RedisOperations<K, V> is converted to BoundListOperations<K, V> here
        this.ops = operations.opsForList();
    }
}

Question_4: Why getConnection().bRPopLPush is accepting srcKey, dstKey as byte[] instead of String ..?

Sorry for many questions, it is all raised because i don't find proper java doc in spring data OR tutorials to explain the usage.

Kanagavelu Sugumar
  • 18,766
  • 20
  • 94
  • 101

2 Answers2

0

Regarding question 4: First of all, it's important to note that Redis keys and values can be any binary. Spring-data templates abstract this away and let developers deal with Java objects rather than byte arrays. See the following quote from the spring-data reference:

...The template offers a high-level abstraction for Redis interactions. While RedisConnection offers low level methods that accept and return binary values (byte arrays), the template takes care of serialization and connection management, freeing the user from dealing with such details.

It seems that when working with RedisConnection, Spring doesn't know what type your key or value is, and it makes no effort to convert an object (e.g., String) to the binary Redis understands, hence, you are required to pass the raw binary to Redis.

asherbret
  • 5,439
  • 4
  • 38
  • 58
0

First, call RedisTemplate.opsForList() to get ListOperations. Then, use ListOperations.rightPopAndLeftPush(K sourceKey, K destinationKey, long timeout, TimeUnit unit) to do BRPOPLPUSH.

Anton N
  • 2,317
  • 24
  • 28